diff options
author | Spp <spp@jorge.gr> | 2013-05-21 09:41:13 +0200 |
---|---|---|
committer | Spp <spp@jorge.gr> | 2013-05-21 09:41:13 +0200 |
commit | 1b6fb2b6959f504d9e33d2326691cf43a04690d2 (patch) | |
tree | 31671ddd62612c27e1e821408956b9a8ff52a0ab | |
parent | 82dc639882d2d51a8bde9bcd47b773be435a5a12 (diff) | |
parent | 243c325ca4323feb4f7f80c0ecd3873c78cbf887 (diff) |
Merge branch 'master' into 4.3.4 [NOTE: There are parts of code marked as "REVIEW - MERGE" That needs some review)
Conflicts:
src/server/game/DataStores/DBCStores.cpp
src/server/game/DataStores/DBCStores.h
src/server/game/DataStores/DBCfmt.h
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Entities/Unit/Unit.h
src/server/game/Handlers/AuctionHouseHandler.cpp
src/server/game/Handlers/GroupHandler.cpp
src/server/game/Movement/Spline/MovementTypedefs.h
src/server/game/Spells/Auras/SpellAuraEffects.cpp
src/server/game/Spells/SpellInfo.cpp
src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
src/server/scripts/Spells/spell_generic.cpp
211 files changed, 16749 insertions, 7598 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 7f91f862d0c..6e3e8574b0f 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -14,7 +14,7 @@ G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License) jemalloc (a general-purpose scalable concurrent malloc-implementation) http://www.canonware.com/jemalloc/ - Version: 2.1.0 + Version: 3.3.1 MySQL (the world's most popular open source database software) http://www.mysql.com/ diff --git a/dep/gsoap/CMakeLists.txt b/dep/gsoap/CMakeLists.txt index 71ad9a0128b..e7ebcc18db2 100644 --- a/dep/gsoap/CMakeLists.txt +++ b/dep/gsoap/CMakeLists.txt @@ -22,3 +22,5 @@ include_directories( add_definitions(-D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=0) add_library(gsoap STATIC ${gsoap_STAT_SRCS}) + +set_target_properties(gsoap PROPERTIES LINKER_LANGUAGE CXX) diff --git a/dep/jemalloc/CMakeLists.txt b/dep/jemalloc/CMakeLists.txt index 1961f3f4dfa..95c3cb05621 100644 --- a/dep/jemalloc/CMakeLists.txt +++ b/dep/jemalloc/CMakeLists.txt @@ -8,16 +8,53 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB sources src/*.c) +# We need to generate the jemalloc_def.h header based on platform-specific settings +if (PLATFORM EQUAL 32) + set(JEM_SIZEDEF 2) + set(JEM_TLSMODEL) +else() + set(JEM_SIZEDEF 3) + set(JEM_TLSMODEL "__attribute__\(\(tls_model\(\"initial-exec\"\)\)\)") +endif() +# Create the header, so we can use it +configure_file( + "${CMAKE_SOURCE_DIR}/dep/jemalloc/jemalloc_defs.h.in.cmake" + "${BUILDDIR}/jemalloc_defs.h" + @ONLY +) + +# Done, let's continue set(jemalloc_STAT_SRC - ${sources} + ${CMAKE_CURRENT_SOURCE_DIR}/src/arena.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/base.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/bitmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_dss.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_mmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ckh.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ctl.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/extent.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hash.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/huge.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mb.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/prof.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/quarantine.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/rtree.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/stats.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tcache.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tsd.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c ) include_directories( + ${BUILDDIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/include ) add_definitions(-D_GNU_SOURCE -D_REENTRANT) -add_library(jemalloc STATIC ${sources}) +add_library(jemalloc STATIC ${jemalloc_STAT_SRC}) diff --git a/dep/jemalloc/COPYING b/dep/jemalloc/COPYING index 10ade120049..019e8132275 100644 --- a/dep/jemalloc/COPYING +++ b/dep/jemalloc/COPYING @@ -1,9 +1,10 @@ Unless otherwise specified, files in the jemalloc source distribution are -subject to the following licenses: +subject to the following license: -------------------------------------------------------------------------------- -Copyright (C) 2002-2010 Jason Evans <jasone@canonware.com>. +Copyright (C) 2002-2013 Jason Evans <jasone@canonware.com>. All rights reserved. -Copyright (C) 2007-2010 Mozilla Foundation. All rights reserved. +Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. +Copyright (C) 2009-2013 Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -24,28 +25,3 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -Copyright (C) 2009-2010 Facebook, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. -* Neither the name of Facebook, Inc. nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- diff --git a/dep/jemalloc/ChangeLog b/dep/jemalloc/ChangeLog new file mode 100644 index 00000000000..fc096d8f42f --- /dev/null +++ b/dep/jemalloc/ChangeLog @@ -0,0 +1,425 @@ +Following are change highlights associated with official releases. Important +bug fixes are all mentioned, but internal enhancements are omitted here for +brevity (even though they are more fun to write about). Much more detail can be +found in the git revision history: + + http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git + git://canonware.com/jemalloc.git + +* 3.3.1 (March 6, 2013) + + This version fixes bugs that are typically encountered only when utilizing + custom run-time options. + + Bug fixes: + - Fix a locking order bug that could cause deadlock during fork if heap + profiling were enabled. + - Fix a chunk recycling bug that could cause the allocator to lose track of + whether a chunk was zeroed. On FreeBSD, NetBSD, and OS X, it could cause + corruption if allocating via sbrk(2) (unlikely unless running with the + "dss:primary" option specified). This was completely harmless on Linux + unless using mlockall(2) (and unlikely even then, unless the + --disable-munmap configure option or the "dss:primary" option was + specified). This regression was introduced in 3.1.0 by the + mlockall(2)/madvise(2) interaction fix. + - Fix TLS-related memory corruption that could occur during thread exit if the + thread never allocated memory. Only the quarantine and prof facilities were + susceptible. + - Fix two quarantine bugs: + + Internal reallocation of the quarantined object array leaked the old + array. + + Reallocation failure for internal reallocation of the quarantined object + array (very unlikely) resulted in memory corruption. + - Fix Valgrind integration to annotate all internally allocated memory in a + way that keeps Valgrind happy about internal data structure access. + - Fix building for s390 systems. + +* 3.3.0 (January 23, 2013) + + This version includes a few minor performance improvements in addition to the + listed new features and bug fixes. + + New features: + - Add clipping support to lg_chunk option processing. + - Add the --enable-ivsalloc option. + - Add the --without-export option. + - Add the --disable-zone-allocator option. + + Bug fixes: + - Fix "arenas.extend" mallctl to output the number of arenas. + - Fix chunk_recycyle() to unconditionally inform Valgrind that returned memory + is undefined. + - Fix build break on FreeBSD related to alloca.h. + +* 3.2.0 (November 9, 2012) + + In addition to a couple of bug fixes, this version modifies page run + allocation and dirty page purging algorithms in order to better control + page-level virtual memory fragmentation. + + Incompatible changes: + - Change the "opt.lg_dirty_mult" default from 5 to 3 (32:1 to 8:1). + + Bug fixes: + - Fix dss/mmap allocation precedence code to use recyclable mmap memory only + after primary dss allocation fails. + - Fix deadlock in the "arenas.purge" mallctl. This regression was introduced + in 3.1.0 by the addition of the "arena.<i>.purge" mallctl. + +* 3.1.0 (October 16, 2012) + + New features: + - Auto-detect whether running inside Valgrind, thus removing the need to + manually specify MALLOC_CONF=valgrind:true. + - Add the "arenas.extend" mallctl, which allows applications to create + manually managed arenas. + - Add the ALLOCM_ARENA() flag for {,r,d}allocm(). + - Add the "opt.dss", "arena.<i>.dss", and "stats.arenas.<i>.dss" mallctls, + which provide control over dss/mmap precedence. + - Add the "arena.<i>.purge" mallctl, which obsoletes "arenas.purge". + - Define LG_QUANTUM for hppa. + + Incompatible changes: + - Disable tcache by default if running inside Valgrind, in order to avoid + making unallocated objects appear reachable to Valgrind. + - Drop const from malloc_usable_size() argument on Linux. + + Bug fixes: + - Fix heap profiling crash if sampled object is freed via realloc(p, 0). + - Remove const from __*_hook variable declarations, so that glibc can modify + them during process forking. + - Fix mlockall(2)/madvise(2) interaction. + - Fix fork(2)-related deadlocks. + - Fix error return value for "thread.tcache.enabled" mallctl. + +* 3.0.0 (May 11, 2012) + + Although this version adds some major new features, the primary focus is on + internal code cleanup that facilitates maintainability and portability, most + of which is not reflected in the ChangeLog. This is the first release to + incorporate substantial contributions from numerous other developers, and the + result is a more broadly useful allocator (see the git revision history for + contribution details). Note that the license has been unified, thanks to + Facebook granting a license under the same terms as the other copyright + holders (see COPYING). + + New features: + - Implement Valgrind support, redzones, and quarantine. + - Add support for additional platforms: + + FreeBSD + + Mac OS X Lion + + MinGW + + Windows (no support yet for replacing the system malloc) + - Add support for additional architectures: + + MIPS + + SH4 + + Tilera + - Add support for cross compiling. + - Add nallocm(), which rounds a request size up to the nearest size class + without actually allocating. + - Implement aligned_alloc() (blame C11). + - Add the "thread.tcache.enabled" mallctl. + - Add the "opt.prof_final" mallctl. + - Update pprof (from gperftools 2.0). + - Add the --with-mangling option. + - Add the --disable-experimental option. + - Add the --disable-munmap option, and make it the default on Linux. + - Add the --enable-mremap option, which disables use of mremap(2) by default. + + Incompatible changes: + - Enable stats by default. + - Enable fill by default. + - Disable lazy locking by default. + - Rename the "tcache.flush" mallctl to "thread.tcache.flush". + - Rename the "arenas.pagesize" mallctl to "arenas.page". + - Change the "opt.lg_prof_sample" default from 0 to 19 (1 B to 512 KiB). + - Change the "opt.prof_accum" default from true to false. + + Removed features: + - Remove the swap feature, including the "config.swap", "swap.avail", + "swap.prezeroed", "swap.nfds", and "swap.fds" mallctls. + - Remove highruns statistics, including the + "stats.arenas.<i>.bins.<j>.highruns" and + "stats.arenas.<i>.lruns.<j>.highruns" mallctls. + - As part of small size class refactoring, remove the "opt.lg_[qc]space_max", + "arenas.cacheline", "arenas.subpage", "arenas.[tqcs]space_{min,max}", and + "arenas.[tqcs]bins" mallctls. + - Remove the "arenas.chunksize" mallctl. + - Remove the "opt.lg_prof_tcmax" option. + - Remove the "opt.lg_prof_bt_max" option. + - Remove the "opt.lg_tcache_gc_sweep" option. + - Remove the --disable-tiny option, including the "config.tiny" mallctl. + - Remove the --enable-dynamic-page-shift configure option. + - Remove the --enable-sysv configure option. + + Bug fixes: + - Fix a statistics-related bug in the "thread.arena" mallctl that could cause + invalid statistics and crashes. + - Work around TLS deallocation via free() on Linux. This bug could cause + write-after-free memory corruption. + - Fix a potential deadlock that could occur during interval- and + growth-triggered heap profile dumps. + - Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags. + - Fix chunk_alloc_dss() to stop claiming memory is zeroed. This bug could + cause memory corruption and crashes with --enable-dss specified. + - Fix fork-related bugs that could cause deadlock in children between fork + and exec. + - Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter. + - Fix realloc(p, 0) to act like free(p). + - Do not enforce minimum alignment in memalign(). + - Check for NULL pointer in malloc_usable_size(). + - Fix an off-by-one heap profile statistics bug that could be observed in + interval- and growth-triggered heap profiles. + - Fix the "epoch" mallctl to update cached stats even if the passed in epoch + is 0. + - Fix bin->runcur management to fix a layout policy bug. This bug did not + affect correctness. + - Fix a bug in choose_arena_hard() that potentially caused more arenas to be + initialized than necessary. + - Add missing "opt.lg_tcache_max" mallctl implementation. + - Use glibc allocator hooks to make mixed allocator usage less likely. + - Fix build issues for --disable-tcache. + - Don't mangle pthread_create() when --with-private-namespace is specified. + +* 2.2.5 (November 14, 2011) + + Bug fixes: + - Fix huge_ralloc() race when using mremap(2). This is a serious bug that + could cause memory corruption and/or crashes. + - Fix huge_ralloc() to maintain chunk statistics. + - Fix malloc_stats_print(..., "a") output. + +* 2.2.4 (November 5, 2011) + + Bug fixes: + - Initialize arenas_tsd before using it. This bug existed for 2.2.[0-3], as + well as for --disable-tls builds in earlier releases. + - Do not assume a 4 KiB page size in test/rallocm.c. + +* 2.2.3 (August 31, 2011) + + This version fixes numerous bugs related to heap profiling. + + Bug fixes: + - Fix a prof-related race condition. This bug could cause memory corruption, + but only occurred in non-default configurations (prof_accum:false). + - Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is + excluded from backtraces). + - Fix a prof-related bug in realloc() (only triggered by OOM errors). + - Fix prof-related bugs in allocm() and rallocm(). + - Fix prof_tdata_cleanup() for --disable-tls builds. + - Fix a relative include path, to fix objdir builds. + +* 2.2.2 (July 30, 2011) + + Bug fixes: + - Fix a build error for --disable-tcache. + - Fix assertions in arena_purge() (for real this time). + - Add the --with-private-namespace option. This is a workaround for symbol + conflicts that can inadvertently arise when using static libraries. + +* 2.2.1 (March 30, 2011) + + Bug fixes: + - Implement atomic operations for x86/x64. This fixes compilation failures + for versions of gcc that are still in wide use. + - Fix an assertion in arena_purge(). + +* 2.2.0 (March 22, 2011) + + This version incorporates several improvements to algorithms and data + structures that tend to reduce fragmentation and increase speed. + + New features: + - Add the "stats.cactive" mallctl. + - Update pprof (from google-perftools 1.7). + - Improve backtracing-related configuration logic, and add the + --disable-prof-libgcc option. + + Bug fixes: + - Change default symbol visibility from "internal", to "hidden", which + decreases the overhead of library-internal function calls. + - Fix symbol visibility so that it is also set on OS X. + - Fix a build dependency regression caused by the introduction of the .pic.o + suffix for PIC object files. + - Add missing checks for mutex initialization failures. + - Don't use libgcc-based backtracing except on x64, where it is known to work. + - Fix deadlocks on OS X that were due to memory allocation in + pthread_mutex_lock(). + - Heap profiling-specific fixes: + + Fix memory corruption due to integer overflow in small region index + computation, when using a small enough sample interval that profiling + context pointers are stored in small run headers. + + Fix a bootstrap ordering bug that only occurred with TLS disabled. + + Fix a rallocm() rsize bug. + + Fix error detection bugs for aligned memory allocation. + +* 2.1.3 (March 14, 2011) + + Bug fixes: + - Fix a cpp logic regression (due to the "thread.{de,}allocatedp" mallctl fix + for OS X in 2.1.2). + - Fix a "thread.arena" mallctl bug. + - Fix a thread cache stats merging bug. + +* 2.1.2 (March 2, 2011) + + Bug fixes: + - Fix "thread.{de,}allocatedp" mallctl for OS X. + - Add missing jemalloc.a to build system. + +* 2.1.1 (January 31, 2011) + + Bug fixes: + - Fix aligned huge reallocation (affected allocm()). + - Fix the ALLOCM_LG_ALIGN macro definition. + - Fix a heap dumping deadlock. + - Fix a "thread.arena" mallctl bug. + +* 2.1.0 (December 3, 2010) + + This version incorporates some optimizations that can't quite be considered + bug fixes. + + New features: + - Use Linux's mremap(2) for huge object reallocation when possible. + - Avoid locking in mallctl*() when possible. + - Add the "thread.[de]allocatedp" mallctl's. + - Convert the manual page source from roff to DocBook, and generate both roff + and HTML manuals. + + Bug fixes: + - Fix a crash due to incorrect bootstrap ordering. This only impacted + --enable-debug --enable-dss configurations. + - Fix a minor statistics bug for mallctl("swap.avail", ...). + +* 2.0.1 (October 29, 2010) + + Bug fixes: + - Fix a race condition in heap profiling that could cause undefined behavior + if "opt.prof_accum" were disabled. + - Add missing mutex unlocks for some OOM error paths in the heap profiling + code. + - Fix a compilation error for non-C99 builds. + +* 2.0.0 (October 24, 2010) + + This version focuses on the experimental *allocm() API, and on improved + run-time configuration/introspection. Nonetheless, numerous performance + improvements are also included. + + New features: + - Implement the experimental {,r,s,d}allocm() API, which provides a superset + of the functionality available via malloc(), calloc(), posix_memalign(), + realloc(), malloc_usable_size(), and free(). These functions can be used to + allocate/reallocate aligned zeroed memory, ask for optional extra memory + during reallocation, prevent object movement during reallocation, etc. + - Replace JEMALLOC_OPTIONS/JEMALLOC_PROF_PREFIX with MALLOC_CONF, which is + more human-readable, and more flexible. For example: + JEMALLOC_OPTIONS=AJP + is now: + MALLOC_CONF=abort:true,fill:true,stats_print:true + - Port to Apple OS X. Sponsored by Mozilla. + - Make it possible for the application to control thread-->arena mappings via + the "thread.arena" mallctl. + - Add compile-time support for all TLS-related functionality via pthreads TSD. + This is mainly of interest for OS X, which does not support TLS, but has a + TSD implementation with similar performance. + - Override memalign() and valloc() if they are provided by the system. + - Add the "arenas.purge" mallctl, which can be used to synchronously purge all + dirty unused pages. + - Make cumulative heap profiling data optional, so that it is possible to + limit the amount of memory consumed by heap profiling data structures. + - Add per thread allocation counters that can be accessed via the + "thread.allocated" and "thread.deallocated" mallctls. + + Incompatible changes: + - Remove JEMALLOC_OPTIONS and malloc_options (see MALLOC_CONF above). + - Increase default backtrace depth from 4 to 128 for heap profiling. + - Disable interval-based profile dumps by default. + + Bug fixes: + - Remove bad assertions in fork handler functions. These assertions could + cause aborts for some combinations of configure settings. + - Fix strerror_r() usage to deal with non-standard semantics in GNU libc. + - Fix leak context reporting. This bug tended to cause the number of contexts + to be underreported (though the reported number of objects and bytes were + correct). + - Fix a realloc() bug for large in-place growing reallocation. This bug could + cause memory corruption, but it was hard to trigger. + - Fix an allocation bug for small allocations that could be triggered if + multiple threads raced to create a new run of backing pages. + - Enhance the heap profiler to trigger samples based on usable size, rather + than request size. + - Fix a heap profiling bug due to sometimes losing track of requested object + size for sampled objects. + +* 1.0.3 (August 12, 2010) + + Bug fixes: + - Fix the libunwind-based implementation of stack backtracing (used for heap + profiling). This bug could cause zero-length backtraces to be reported. + - Add a missing mutex unlock in library initialization code. If multiple + threads raced to initialize malloc, some of them could end up permanently + blocked. + +* 1.0.2 (May 11, 2010) + + Bug fixes: + - Fix junk filling of large objects, which could cause memory corruption. + - Add MAP_NORESERVE support for chunk mapping, because otherwise virtual + memory limits could cause swap file configuration to fail. Contributed by + Jordan DeLong. + +* 1.0.1 (April 14, 2010) + + Bug fixes: + - Fix compilation when --enable-fill is specified. + - Fix threads-related profiling bugs that affected accuracy and caused memory + to be leaked during thread exit. + - Fix dirty page purging race conditions that could cause crashes. + - Fix crash in tcache flushing code during thread destruction. + +* 1.0.0 (April 11, 2010) + + This release focuses on speed and run-time introspection. Numerous + algorithmic improvements make this release substantially faster than its + predecessors. + + New features: + - Implement autoconf-based configuration system. + - Add mallctl*(), for the purposes of introspection and run-time + configuration. + - Make it possible for the application to manually flush a thread's cache, via + the "tcache.flush" mallctl. + - Base maximum dirty page count on proportion of active memory. + - Compute various addtional run-time statistics, including per size class + statistics for large objects. + - Expose malloc_stats_print(), which can be called repeatedly by the + application. + - Simplify the malloc_message() signature to only take one string argument, + and incorporate an opaque data pointer argument for use by the application + in combination with malloc_stats_print(). + - Add support for allocation backed by one or more swap files, and allow the + application to disable over-commit if swap files are in use. + - Implement allocation profiling and leak checking. + + Removed features: + - Remove the dynamic arena rebalancing code, since thread-specific caching + reduces its utility. + + Bug fixes: + - Modify chunk allocation to work when address space layout randomization + (ASLR) is in use. + - Fix thread cleanup bugs related to TLS destruction. + - Handle 0-size allocation requests in posix_memalign(). + - Fix a chunk leak. The leaked chunks were never touched, so this impacted + virtual memory usage, but not physical memory usage. + +* linux_2008082[78]a (August 27/28, 2008) + + These snapshot releases are the simple result of incorporating Linux-specific + support into the FreeBSD malloc sources. + +-------------------------------------------------------------------------------- +vim:filetype=text:textwidth=80 diff --git a/dep/jemalloc/README b/dep/jemalloc/README index 4d7b552bf3d..7661683bae7 100644 --- a/dep/jemalloc/README +++ b/dep/jemalloc/README @@ -1,10 +1,10 @@ jemalloc is a general-purpose scalable concurrent malloc(3) implementation. -This distribution is a stand-alone "portable" implementation that currently -targets Linux and Apple OS X. jemalloc is included as the default allocator in -the FreeBSD and NetBSD operating systems, and it is used by the Mozilla Firefox -web browser on Microsoft Windows-related platforms. Depending on your needs, -one of the other divergent versions may suit your needs better than this -distribution. +This distribution is a "portable" implementation that currently targets +FreeBSD, Linux, Apple OS X, and MinGW. jemalloc is included as the default +allocator in the FreeBSD and NetBSD operating systems, and it is used by the +Mozilla Firefox web browser on Microsoft Windows-related platforms. Depending +on your needs, one of the other divergent versions may suit your needs better +than this distribution. The COPYING file contains copyright and licensing information. diff --git a/dep/jemalloc/TC_NOTE.txt b/dep/jemalloc/TC_NOTE.txt index 7b045631d8c..7a44e3563c9 100644 --- a/dep/jemalloc/TC_NOTE.txt +++ b/dep/jemalloc/TC_NOTE.txt @@ -2,8 +2,3 @@ Removed from archive, as OSX does not use jemalloc: src/zone.c include/jemalloc/internal/zone.h - -Filename changed, as it messes up Windows-systems (when will Microsoft learn?) : - include/jemalloc/internal/prn.h -> include/jemalloc/internal/jemprn.h - -References to prn.h has been changed to use the new filename where needed. diff --git a/dep/jemalloc/VERSION b/dep/jemalloc/VERSION index 585f53edd80..900c82d1043 100644 --- a/dep/jemalloc/VERSION +++ b/dep/jemalloc/VERSION @@ -1 +1 @@ -2.1.0-0-g1c4b088b08d3bc7617a34387e196ce03716160bf +3.3.1-0-g9ef9d9e8c271cdf14f664b871a8f98c827714784 diff --git a/dep/jemalloc/include/jemalloc/internal/arena.h b/dep/jemalloc/include/jemalloc/internal/arena.h index 9556c2c68f7..f2c18f43543 100644 --- a/dep/jemalloc/include/jemalloc/internal/arena.h +++ b/dep/jemalloc/include/jemalloc/internal/arena.h @@ -2,40 +2,6 @@ #ifdef JEMALLOC_H_TYPES /* - * Subpages are an artificially designated partitioning of pages. Their only - * purpose is to support subpage-spaced size classes. - * - * There must be at least 4 subpages per page, due to the way size classes are - * handled. - */ -#define LG_SUBPAGE 8 -#define SUBPAGE ((size_t)(1U << LG_SUBPAGE)) -#define SUBPAGE_MASK (SUBPAGE - 1) - -/* Return the smallest subpage multiple that is >= s. */ -#define SUBPAGE_CEILING(s) \ - (((s) + SUBPAGE_MASK) & ~SUBPAGE_MASK) - -#ifdef JEMALLOC_TINY - /* Smallest size class to support. */ -# define LG_TINY_MIN LG_SIZEOF_PTR -#endif - -/* - * Maximum size class that is a multiple of the quantum, but not (necessarily) - * a power of 2. Above this size, allocations are rounded up to the nearest - * power of 2. - */ -#define LG_QSPACE_MAX_DEFAULT 7 - -/* - * Maximum size class that is a multiple of the cacheline, but not (necessarily) - * a power of 2. Above this size, allocations are rounded up to the nearest - * power of 2. - */ -#define LG_CSPACE_MAX_DEFAULT 9 - -/* * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized * as small as possible such that this setting is still honored, without * violating other constraints. The goal is to make runs as small as possible @@ -45,30 +11,42 @@ * point is implicitly RUN_BFP bits to the left. * * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be - * honored for some/all object sizes, since there is one bit of header overhead - * per object (plus a constant). This constraint is relaxed (ignored) for runs - * that are so small that the per-region overhead is greater than: + * honored for some/all object sizes, since when heap profiling is enabled + * there is one pointer of header overhead per object (plus a constant). This + * constraint is relaxed (ignored) for runs that are so small that the + * per-region overhead is greater than: * - * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP)) + * (RUN_MAX_OVRHD / (reg_interval << (3+RUN_BFP)) */ #define RUN_BFP 12 /* \/ Implicit binary fixed point. */ #define RUN_MAX_OVRHD 0x0000003dU #define RUN_MAX_OVRHD_RELAX 0x00001800U +/* Maximum number of regions in one run. */ +#define LG_RUN_MAXREGS 11 +#define RUN_MAXREGS (1U << LG_RUN_MAXREGS) + +/* + * Minimum redzone size. Redzones may be larger than this if necessary to + * preserve region alignment. + */ +#define REDZONE_MINSIZE 16 + /* * The minimum ratio of active:dirty pages per arena is computed as: * * (nactive >> opt_lg_dirty_mult) >= ndirty * - * So, supposing that opt_lg_dirty_mult is 5, there can be no less than 32 - * times as many active pages as dirty pages. + * So, supposing that opt_lg_dirty_mult is 3, there can be no less than 8 times + * as many active pages as dirty pages. */ -#define LG_DIRTY_MULT_DEFAULT 5 +#define LG_DIRTY_MULT_DEFAULT 3 typedef struct arena_chunk_map_s arena_chunk_map_t; typedef struct arena_chunk_s arena_chunk_t; typedef struct arena_run_s arena_run_t; +typedef struct arena_bin_info_s arena_bin_info_t; typedef struct arena_bin_s arena_bin_t; typedef struct arena_s arena_t; @@ -78,11 +56,20 @@ typedef struct arena_s arena_t; /* Each element of the chunk map corresponds to one page within the chunk. */ struct arena_chunk_map_s { +#ifndef JEMALLOC_PROF + /* + * Overlay prof_ctx in order to allow it to be referenced by dead code. + * Such antics aren't warranted for per arena data structures, but + * chunk map overhead accounts for a percentage of memory, rather than + * being just a fixed cost. + */ + union { +#endif union { /* * Linkage for run trees. There are two disjoint uses: * - * 1) arena_t's runs_avail_{clean,dirty} trees. + * 1) arena_t's runs_avail tree. * 2) arena_run_t conceptually uses this linkage for in-use * non-full runs, rather than directly embedding linkage. */ @@ -96,24 +83,25 @@ struct arena_chunk_map_s { ql_elm(arena_chunk_map_t) ql_link; } u; -#ifdef JEMALLOC_PROF /* Profile counters, used for large object runs. */ prof_ctx_t *prof_ctx; +#ifndef JEMALLOC_PROF + }; /* union { ... }; */ #endif /* * Run address (or size) and various flags are stored together. The bit * layout looks like (assuming 32-bit system): * - * ???????? ???????? ????---- ----dzla + * ???????? ???????? ????nnnn nnnndula * * ? : Unallocated: Run address for first/last pages, unset for internal * pages. * Small: Run page offset. * Large: Run size for first page, unset for trailing pages. - * - : Unused. + * n : binind for small size class, BININD_INVALID for large size class. * d : dirty? - * z : zeroed? + * u : unzeroed? * l : large? * a : allocated? * @@ -121,7 +109,8 @@ struct arena_chunk_map_s { * * p : run page offset * s : run size - * c : (binind+1) for size class (used only if prof_promote is true) + * n : binind for size class; large objects set these to BININD_INVALID + * except for promoted allocations (see prof_promote) * x : don't care * - : 0 * + : 1 @@ -129,37 +118,38 @@ struct arena_chunk_map_s { * [dula] : bit unset * * Unallocated (clean): - * ssssssss ssssssss ssss---- ----du-- - * xxxxxxxx xxxxxxxx xxxx---- -----Uxx - * ssssssss ssssssss ssss---- ----dU-- + * ssssssss ssssssss ssss++++ ++++du-a + * xxxxxxxx xxxxxxxx xxxxxxxx xxxx-Uxx + * ssssssss ssssssss ssss++++ ++++dU-a * * Unallocated (dirty): - * ssssssss ssssssss ssss---- ----D--- - * xxxxxxxx xxxxxxxx xxxx---- ----xxxx - * ssssssss ssssssss ssss---- ----D--- + * ssssssss ssssssss ssss++++ ++++D--a + * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx + * ssssssss ssssssss ssss++++ ++++D--a * * Small: - * pppppppp pppppppp pppp---- ----d--a - * pppppppp pppppppp pppp---- -------a - * pppppppp pppppppp pppp---- ----d--a + * pppppppp pppppppp ppppnnnn nnnnd--A + * pppppppp pppppppp ppppnnnn nnnn---A + * pppppppp pppppppp ppppnnnn nnnnd--A * * Large: - * ssssssss ssssssss ssss---- ----D-la - * xxxxxxxx xxxxxxxx xxxx---- ----xxxx - * -------- -------- -------- ----D-la + * ssssssss ssssssss ssss++++ ++++D-LA + * xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx + * -------- -------- ----++++ ++++D-LA * - * Large (sampled, size <= PAGE_SIZE): - * ssssssss ssssssss sssscccc ccccD-la + * Large (sampled, size <= PAGE): + * ssssssss ssssssss ssssnnnn nnnnD-LA * - * Large (not sampled, size == PAGE_SIZE): - * ssssssss ssssssss ssss---- ----D-la + * Large (not sampled, size == PAGE): + * ssssssss ssssssss ssss++++ ++++D-LA */ size_t bits; -#ifdef JEMALLOC_PROF -#define CHUNK_MAP_CLASS_SHIFT 4 -#define CHUNK_MAP_CLASS_MASK ((size_t)0xff0U) -#endif -#define CHUNK_MAP_FLAGS_MASK ((size_t)0xfU) +#define CHUNK_MAP_BININD_SHIFT 4 +#define BININD_INVALID ((size_t)0xffU) +/* CHUNK_MAP_BININD_MASK == (BININD_INVALID << CHUNK_MAP_BININD_SHIFT) */ +#define CHUNK_MAP_BININD_MASK ((size_t)0xff0U) +#define CHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK +#define CHUNK_MAP_FLAGS_MASK ((size_t)0xcU) #define CHUNK_MAP_DIRTY ((size_t)0x8U) #define CHUNK_MAP_UNZEROED ((size_t)0x4U) #define CHUNK_MAP_LARGE ((size_t)0x2U) @@ -172,20 +162,24 @@ typedef rb_tree(arena_chunk_map_t) arena_run_tree_t; /* Arena chunk header. */ struct arena_chunk_s { /* Arena that owns the chunk. */ - arena_t *arena; + arena_t *arena; - /* Linkage for the arena's chunks_dirty list. */ - ql_elm(arena_chunk_t) link_dirty; - - /* - * True if the chunk is currently in the chunks_dirty list, due to - * having at some point contained one or more dirty pages. Removal - * from chunks_dirty is lazy, so (dirtied && ndirty == 0) is possible. - */ - bool dirtied; + /* Linkage for tree of arena chunks that contain dirty runs. */ + rb_node(arena_chunk_t) dirty_link; /* Number of dirty pages. */ - size_t ndirty; + size_t ndirty; + + /* Number of available runs. */ + size_t nruns_avail; + + /* + * Number of available run adjacencies. Clean and dirty available runs + * are not coalesced, which causes virtual memory fragmentation. The + * ratio of (nruns_avail-nruns_adjac):nruns_adjac is used for tracking + * this fragmentation. + * */ + size_t nruns_adjac; /* * Map of pages within chunk that keeps track of free/large/small. The @@ -193,29 +187,97 @@ struct arena_chunk_s { * need to be tracked in the map. This omission saves a header page * for common chunk sizes (e.g. 4 MiB). */ - arena_chunk_map_t map[1]; /* Dynamically sized. */ + arena_chunk_map_t map[1]; /* Dynamically sized. */ }; typedef rb_tree(arena_chunk_t) arena_chunk_tree_t; struct arena_run_s { -#ifdef JEMALLOC_DEBUG - uint32_t magic; -# define ARENA_RUN_MAGIC 0x384adf93 -#endif - /* Bin this run is associated with. */ arena_bin_t *bin; - /* Stack of available freed regions, or NULL. */ - void *avail; - - /* Next region that has never been allocated, or run boundary. */ - void *next; + /* Index of next region that has never been allocated, or nregs. */ + uint32_t nextind; /* Number of free regions in run. */ unsigned nfree; }; +/* + * Read-only information associated with each element of arena_t's bins array + * is stored separately, partly to reduce memory usage (only one copy, rather + * than one per arena), but mainly to avoid false cacheline sharing. + * + * Each run has the following layout: + * + * /--------------------\ + * | arena_run_t header | + * | ... | + * bitmap_offset | bitmap | + * | ... | + * ctx0_offset | ctx map | + * | ... | + * |--------------------| + * | redzone | + * reg0_offset | region 0 | + * | redzone | + * |--------------------| \ + * | redzone | | + * | region 1 | > reg_interval + * | redzone | / + * |--------------------| + * | ... | + * | ... | + * | ... | + * |--------------------| + * | redzone | + * | region nregs-1 | + * | redzone | + * |--------------------| + * | alignment pad? | + * \--------------------/ + * + * reg_interval has at least the same minimum alignment as reg_size; this + * preserves the alignment constraint that sa2u() depends on. Alignment pad is + * either 0 or redzone_size; it is present only if needed to align reg0_offset. + */ +struct arena_bin_info_s { + /* Size of regions in a run for this bin's size class. */ + size_t reg_size; + + /* Redzone size. */ + size_t redzone_size; + + /* Interval between regions (reg_size + (redzone_size << 1)). */ + size_t reg_interval; + + /* Total size of a run for this bin's size class. */ + size_t run_size; + + /* Total number of regions in a run for this bin's size class. */ + uint32_t nregs; + + /* + * Offset of first bitmap_t element in a run header for this bin's size + * class. + */ + uint32_t bitmap_offset; + + /* + * Metadata used to manipulate bitmaps for runs associated with this + * bin. + */ + bitmap_info_t bitmap_info; + + /* + * Offset of first (prof_ctx_t *) in a run header for this bin's size + * class, or 0 if (config_prof == false || opt_prof == false). + */ + uint32_t ctx0_offset; + + /* Offset of first region in a run for this bin's size class. */ + uint32_t reg0_offset; +}; + struct arena_bin_s { /* * All operations on runcur, runs, and stats require that lock be @@ -240,64 +302,43 @@ struct arena_bin_s { */ arena_run_tree_t runs; - /* Size of regions in a run for this bin's size class. */ - size_t reg_size; - - /* Total size of a run for this bin's size class. */ - size_t run_size; - - /* Total number of regions in a run for this bin's size class. */ - uint32_t nregs; - -#ifdef JEMALLOC_PROF - /* - * Offset of first (prof_ctx_t *) in a run header for this bin's size - * class, or 0 if (opt_prof == false). - */ - uint32_t ctx0_offset; -#endif - - /* Offset of first region in a run for this bin's size class. */ - uint32_t reg0_offset; - -#ifdef JEMALLOC_STATS /* Bin statistics. */ malloc_bin_stats_t stats; -#endif }; struct arena_s { -#ifdef JEMALLOC_DEBUG - uint32_t magic; -# define ARENA_MAGIC 0x947d3d24 -#endif - /* This arena's index within the arenas array. */ unsigned ind; /* - * All non-bin-related operations on this arena require that lock be - * locked. + * Number of threads currently assigned to this arena. This field is + * protected by arenas_lock. + */ + unsigned nthreads; + + /* + * There are three classes of arena operations from a locking + * perspective: + * 1) Thread asssignment (modifies nthreads) is protected by + * arenas_lock. + * 2) Bin-related operations are protected by bin locks. + * 3) Chunk- and run-related operations are protected by this mutex. */ malloc_mutex_t lock; -#ifdef JEMALLOC_STATS arena_stats_t stats; -# ifdef JEMALLOC_TCACHE /* * List of tcaches for extant threads associated with this arena. * Stats from these are merged incrementally, and at exit. */ ql_head(tcache_t) tcache_ql; -# endif -#endif -#ifdef JEMALLOC_PROF uint64_t prof_accumbytes; -#endif - /* List of dirty-page-containing chunks this arena manages. */ - ql_head(arena_chunk_t) chunks_dirty; + dss_prec_t dss_prec; + + /* Tree of dirty-page-containing chunks this arena manages. */ + arena_chunk_tree_t chunks_dirty; /* * In order to avoid rapid chunk allocation/deallocation when an arena @@ -332,169 +373,418 @@ struct arena_s { /* * Size/address-ordered trees of this arena's available runs. The trees - * are used for first-best-fit run allocation. The dirty tree contains - * runs with dirty pages (i.e. very likely to have been touched and - * therefore have associated physical pages), whereas the clean tree - * contains runs with pages that either have no associated physical - * pages, or have pages that the kernel may recycle at any time due to - * previous madvise(2) calls. The dirty tree is used in preference to - * the clean tree for allocations, because using dirty pages reduces - * the amount of dirty purging necessary to keep the active:dirty page - * ratio below the purge threshold. + * are used for first-best-fit run allocation. */ - arena_avail_tree_t runs_avail_clean; - arena_avail_tree_t runs_avail_dirty; + arena_avail_tree_t runs_avail; - /* - * bins is used to store trees of free regions of the following sizes, - * assuming a 16-byte quantum, 4 KiB page size, and default - * JEMALLOC_OPTIONS. - * - * bins[i] | size | - * --------+--------+ - * 0 | 2 | - * 1 | 4 | - * 2 | 8 | - * --------+--------+ - * 3 | 16 | - * 4 | 32 | - * 5 | 48 | - * : : - * 8 | 96 | - * 9 | 112 | - * 10 | 128 | - * --------+--------+ - * 11 | 192 | - * 12 | 256 | - * 13 | 320 | - * 14 | 384 | - * 15 | 448 | - * 16 | 512 | - * --------+--------+ - * 17 | 768 | - * 18 | 1024 | - * 19 | 1280 | - * : : - * 27 | 3328 | - * 28 | 3584 | - * 29 | 3840 | - * --------+--------+ - * 30 | 4 KiB | - * 31 | 6 KiB | - * 33 | 8 KiB | - * : : - * 43 | 28 KiB | - * 44 | 30 KiB | - * 45 | 32 KiB | - * --------+--------+ - */ - arena_bin_t bins[1]; /* Dynamically sized. */ + /* bins is used to store trees of free regions. */ + arena_bin_t bins[NBINS]; }; #endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -extern size_t opt_lg_qspace_max; -extern size_t opt_lg_cspace_max; -extern ssize_t opt_lg_dirty_mult; -extern uint8_t const *small_size2bin; +extern ssize_t opt_lg_dirty_mult; +/* + * small_size2bin is a compact lookup table that rounds request sizes up to + * size classes. In order to reduce cache footprint, the table is compressed, + * and all accesses are via the SMALL_SIZE2BIN macro. + */ +extern uint8_t const small_size2bin[]; +#define SMALL_SIZE2BIN(s) (small_size2bin[(s-1) >> LG_TINY_MIN]) -/* Various bin-related settings. */ -#ifdef JEMALLOC_TINY /* Number of (2^n)-spaced tiny bins. */ -# define ntbins ((unsigned)(LG_QUANTUM - LG_TINY_MIN)) -#else -# define ntbins 0 -#endif -extern unsigned nqbins; /* Number of quantum-spaced bins. */ -extern unsigned ncbins; /* Number of cacheline-spaced bins. */ -extern unsigned nsbins; /* Number of subpage-spaced bins. */ -extern unsigned nbins; -#ifdef JEMALLOC_TINY -# define tspace_max ((size_t)(QUANTUM >> 1)) -#endif -#define qspace_min QUANTUM -extern size_t qspace_max; -extern size_t cspace_min; -extern size_t cspace_max; -extern size_t sspace_min; -extern size_t sspace_max; -#define small_maxclass sspace_max +extern arena_bin_info_t arena_bin_info[NBINS]; +/* Number of large size classes. */ #define nlclasses (chunk_npages - map_bias) void arena_purge_all(arena_t *arena); -#ifdef JEMALLOC_PROF -void arena_prof_accum(arena_t *arena, uint64_t accumbytes); -#endif -#ifdef JEMALLOC_TCACHE void arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, - size_t binind -# ifdef JEMALLOC_PROF - , uint64_t prof_accumbytes -# endif - ); -#endif + size_t binind, uint64_t prof_accumbytes); +void arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, + bool zero); +void arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info); void *arena_malloc_small(arena_t *arena, size_t size, bool zero); void *arena_malloc_large(arena_t *arena, size_t size, bool zero); -void *arena_malloc(size_t size, bool zero); -void *arena_palloc(arena_t *arena, size_t size, size_t alloc_size, - size_t alignment, bool zero); -size_t arena_salloc(const void *ptr); -#ifdef JEMALLOC_PROF +void *arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero); void arena_prof_promoted(const void *ptr, size_t size); -size_t arena_salloc_demote(const void *ptr); -#endif -void arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, +void arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr, arena_chunk_map_t *mapelm); +void arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, + size_t pageind, arena_chunk_map_t *mapelm); +void arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, + size_t pageind); +void arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk, + void *ptr); void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr); -#ifdef JEMALLOC_STATS -void arena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty, - arena_stats_t *astats, malloc_bin_stats_t *bstats, - malloc_large_stats_t *lstats); -#endif void *arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, bool zero); -void *arena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero); +void *arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, + size_t extra, size_t alignment, bool zero, bool try_tcache_alloc, + bool try_tcache_dalloc); +dss_prec_t arena_dss_prec_get(arena_t *arena); +void arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); +void arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, + size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats, + malloc_large_stats_t *lstats); bool arena_new(arena_t *arena, unsigned ind); -bool arena_boot(void); +void arena_boot(void); +void arena_prefork(arena_t *arena); +void arena_postfork_parent(arena_t *arena); +void arena_postfork_child(arena_t *arena); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE -unsigned arena_run_regind(arena_run_t *run, arena_bin_t *bin, - const void *ptr, size_t size); -# ifdef JEMALLOC_PROF +arena_chunk_map_t *arena_mapp_get(arena_chunk_t *chunk, size_t pageind); +size_t *arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, + size_t pageind); +size_t arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind); +size_t arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind); +void arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, + size_t size, size_t flags); +void arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind, + size_t size); +void arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, + size_t size, size_t flags); +void arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind, + size_t binind); +void arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, + size_t runind, size_t binind, size_t flags); +void arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind, + size_t unzeroed); +bool arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes); +bool arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes); +bool arena_prof_accum(arena_t *arena, uint64_t accumbytes); +size_t arena_ptr_small_binind_get(const void *ptr, size_t mapbits); +size_t arena_bin_index(arena_t *arena, arena_bin_t *bin); +unsigned arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, + const void *ptr); prof_ctx_t *arena_prof_ctx_get(const void *ptr); void arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); -# endif -void arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr); +void *arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache); +size_t arena_salloc(const void *ptr, bool demote); +void arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, + bool try_tcache); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_)) -JEMALLOC_INLINE unsigned -arena_run_regind(arena_run_t *run, arena_bin_t *bin, const void *ptr, +# ifdef JEMALLOC_ARENA_INLINE_A +JEMALLOC_ALWAYS_INLINE arena_chunk_map_t * +arena_mapp_get(arena_chunk_t *chunk, size_t pageind) +{ + + assert(pageind >= map_bias); + assert(pageind < chunk_npages); + + return (&chunk->map[pageind-map_bias]); +} + +JEMALLOC_ALWAYS_INLINE size_t * +arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind) +{ + + return (&arena_mapp_get(chunk, pageind)->bits); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_get(arena_chunk_t *chunk, size_t pageind) +{ + + return (*arena_mapbitsp_get(chunk, pageind)); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0); + return (mapbits & ~PAGE_MASK); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == + (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)); + return (mapbits & ~PAGE_MASK); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == + CHUNK_MAP_ALLOCATED); + return (mapbits >> LG_PAGE); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + size_t binind; + + mapbits = arena_mapbits_get(chunk, pageind); + binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT; + assert(binind < NBINS || binind == BININD_INVALID); + return (binind); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + return (mapbits & CHUNK_MAP_DIRTY); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + return (mapbits & CHUNK_MAP_UNZEROED); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + return (mapbits & CHUNK_MAP_LARGE); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind) +{ + size_t mapbits; + + mapbits = arena_mapbits_get(chunk, pageind); + return (mapbits & CHUNK_MAP_ALLOCATED); +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size, + size_t flags) +{ + size_t *mapbitsp; + + mapbitsp = arena_mapbitsp_get(chunk, pageind); + assert((size & PAGE_MASK) == 0); + assert((flags & ~CHUNK_MAP_FLAGS_MASK) == 0); + assert((flags & (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == flags); + *mapbitsp = size | CHUNK_MAP_BININD_INVALID | flags; +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind, size_t size) { + size_t *mapbitsp; + + mapbitsp = arena_mapbitsp_get(chunk, pageind); + assert((size & PAGE_MASK) == 0); + assert((*mapbitsp & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0); + *mapbitsp = size | (*mapbitsp & PAGE_MASK); +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size, + size_t flags) +{ + size_t *mapbitsp; + size_t unzeroed; + + mapbitsp = arena_mapbitsp_get(chunk, pageind); + assert((size & PAGE_MASK) == 0); + assert((flags & CHUNK_MAP_DIRTY) == flags); + unzeroed = *mapbitsp & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */ + *mapbitsp = size | CHUNK_MAP_BININD_INVALID | flags | unzeroed | + CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind, + size_t binind) +{ + size_t *mapbitsp; + + assert(binind <= BININD_INVALID); + mapbitsp = arena_mapbitsp_get(chunk, pageind); + assert(arena_mapbits_large_size_get(chunk, pageind) == PAGE); + *mapbitsp = (*mapbitsp & ~CHUNK_MAP_BININD_MASK) | (binind << + CHUNK_MAP_BININD_SHIFT); +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind, + size_t binind, size_t flags) +{ + size_t *mapbitsp; + size_t unzeroed; + + assert(binind < BININD_INVALID); + mapbitsp = arena_mapbitsp_get(chunk, pageind); + assert(pageind - runind >= map_bias); + assert((flags & CHUNK_MAP_DIRTY) == flags); + unzeroed = *mapbitsp & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */ + *mapbitsp = (runind << LG_PAGE) | (binind << CHUNK_MAP_BININD_SHIFT) | + flags | unzeroed | CHUNK_MAP_ALLOCATED; +} + +JEMALLOC_ALWAYS_INLINE void +arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind, + size_t unzeroed) +{ + size_t *mapbitsp; + + mapbitsp = arena_mapbitsp_get(chunk, pageind); + *mapbitsp = (*mapbitsp & ~CHUNK_MAP_UNZEROED) | unzeroed; +} + +JEMALLOC_INLINE bool +arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes) +{ + + cassert(config_prof); + assert(prof_interval != 0); + + arena->prof_accumbytes += accumbytes; + if (arena->prof_accumbytes >= prof_interval) { + arena->prof_accumbytes -= prof_interval; + return (true); + } + return (false); +} + +JEMALLOC_INLINE bool +arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes) +{ + + cassert(config_prof); + + if (prof_interval == 0) + return (false); + return (arena_prof_accum_impl(arena, accumbytes)); +} + +JEMALLOC_INLINE bool +arena_prof_accum(arena_t *arena, uint64_t accumbytes) +{ + + cassert(config_prof); + + if (prof_interval == 0) + return (false); + + { + bool ret; + + malloc_mutex_lock(&arena->lock); + ret = arena_prof_accum_impl(arena, accumbytes); + malloc_mutex_unlock(&arena->lock); + return (ret); + } +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_ptr_small_binind_get(const void *ptr, size_t mapbits) +{ + size_t binind; + + binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT; + + if (config_debug) { + arena_chunk_t *chunk; + arena_t *arena; + size_t pageind; + size_t actual_mapbits; + arena_run_t *run; + arena_bin_t *bin; + size_t actual_binind; + arena_bin_info_t *bin_info; + + assert(binind != BININD_INVALID); + assert(binind < NBINS); + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); + arena = chunk->arena; + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + actual_mapbits = arena_mapbits_get(chunk, pageind); + assert(mapbits == actual_mapbits); + assert(arena_mapbits_large_get(chunk, pageind) == 0); + assert(arena_mapbits_allocated_get(chunk, pageind) != 0); + run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - + (actual_mapbits >> LG_PAGE)) << LG_PAGE)); + bin = run->bin; + actual_binind = bin - arena->bins; + assert(binind == actual_binind); + bin_info = &arena_bin_info[actual_binind]; + assert(((uintptr_t)ptr - ((uintptr_t)run + + (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval + == 0); + } + + return (binind); +} +# endif /* JEMALLOC_ARENA_INLINE_A */ + +# ifdef JEMALLOC_ARENA_INLINE_B +JEMALLOC_INLINE size_t +arena_bin_index(arena_t *arena, arena_bin_t *bin) +{ + size_t binind = bin - arena->bins; + assert(binind < NBINS); + return (binind); +} + +JEMALLOC_INLINE unsigned +arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr) +{ unsigned shift, diff, regind; + size_t interval; - assert(run->magic == ARENA_RUN_MAGIC); + /* + * Freeing a pointer lower than region zero can cause assertion + * failure. + */ + assert((uintptr_t)ptr >= (uintptr_t)run + + (uintptr_t)bin_info->reg0_offset); /* * Avoid doing division with a variable divisor if possible. Using * actual division here can reduce allocator throughput by over 20%! */ - diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset); + diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - + bin_info->reg0_offset); /* Rescale (factor powers of 2 out of the numerator and denominator). */ - shift = ffs(size) - 1; + interval = bin_info->reg_interval; + shift = ffs(interval) - 1; diff >>= shift; - size >>= shift; + interval >>= shift; - if (size == 1) { + if (interval == 1) { /* The divisor was a power of 2. */ regind = diff; } else { @@ -506,15 +796,15 @@ arena_run_regind(arena_run_t *run, arena_bin_t *bin, const void *ptr, * * becomes * - * (X * size_invs[D - 3]) >> SIZE_INV_SHIFT + * (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT * * We can omit the first three elements, because we never * divide by 0, and 1 and 2 are both powers of two, which are * handled above. */ -#define SIZE_INV_SHIFT 21 -#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1) - static const unsigned size_invs[] = { +#define SIZE_INV_SHIFT ((sizeof(unsigned) << 3) - LG_RUN_MAXREGS) +#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1) + static const unsigned interval_invs[] = { SIZE_INV(3), SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7), SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11), @@ -525,20 +815,21 @@ arena_run_regind(arena_run_t *run, arena_bin_t *bin, const void *ptr, SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31) }; - if (size <= ((sizeof(size_invs) / sizeof(unsigned)) + 2)) - regind = (diff * size_invs[size - 3]) >> SIZE_INV_SHIFT; - else - regind = diff / size; + if (interval <= ((sizeof(interval_invs) / sizeof(unsigned)) + + 2)) { + regind = (diff * interval_invs[interval - 3]) >> + SIZE_INV_SHIFT; + } else + regind = diff / interval; #undef SIZE_INV #undef SIZE_INV_SHIFT } - assert(diff == regind * size); - assert(regind < bin->nregs); + assert(diff == regind * interval); + assert(regind < bin_info->nregs); return (regind); } -#ifdef JEMALLOC_PROF JEMALLOC_INLINE prof_ctx_t * arena_prof_ctx_get(const void *ptr) { @@ -546,31 +837,33 @@ arena_prof_ctx_get(const void *ptr) arena_chunk_t *chunk; size_t pageind, mapbits; + cassert(config_prof); assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapbits = chunk->map[pageind-map_bias].bits; + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + mapbits = arena_mapbits_get(chunk, pageind); assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); if ((mapbits & CHUNK_MAP_LARGE) == 0) { if (prof_promote) ret = (prof_ctx_t *)(uintptr_t)1U; else { arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> PAGE_SHIFT)) << - PAGE_SHIFT)); - arena_bin_t *bin = run->bin; + (uintptr_t)((pageind - (mapbits >> LG_PAGE)) << + LG_PAGE)); + size_t binind = arena_ptr_small_binind_get(ptr, + mapbits); + arena_bin_info_t *bin_info = &arena_bin_info[binind]; unsigned regind; - assert(run->magic == ARENA_RUN_MAGIC); - regind = arena_run_regind(run, bin, ptr, bin->reg_size); + regind = arena_run_regind(run, bin_info, ptr); ret = *(prof_ctx_t **)((uintptr_t)run + - bin->ctx0_offset + (regind * + bin_info->ctx0_offset + (regind * sizeof(prof_ctx_t *))); } } else - ret = chunk->map[pageind-map_bias].prof_ctx; + ret = arena_mapp_get(chunk, pageind)->prof_ctx; return (ret); } @@ -581,102 +874,148 @@ arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx) arena_chunk_t *chunk; size_t pageind, mapbits; + cassert(config_prof); assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapbits = chunk->map[pageind-map_bias].bits; + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + mapbits = arena_mapbits_get(chunk, pageind); assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); if ((mapbits & CHUNK_MAP_LARGE) == 0) { if (prof_promote == false) { arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> PAGE_SHIFT)) << - PAGE_SHIFT)); - arena_bin_t *bin = run->bin; + (uintptr_t)((pageind - (mapbits >> LG_PAGE)) << + LG_PAGE)); + size_t binind; + arena_bin_info_t *bin_info; unsigned regind; - assert(run->magic == ARENA_RUN_MAGIC); - regind = arena_run_regind(run, bin, ptr, bin->reg_size); + binind = arena_ptr_small_binind_get(ptr, mapbits); + bin_info = &arena_bin_info[binind]; + regind = arena_run_regind(run, bin_info, ptr); - *((prof_ctx_t **)((uintptr_t)run + bin->ctx0_offset + *((prof_ctx_t **)((uintptr_t)run + bin_info->ctx0_offset + (regind * sizeof(prof_ctx_t *)))) = ctx; } else assert((uintptr_t)ctx == (uintptr_t)1U); } else - chunk->map[pageind-map_bias].prof_ctx = ctx; + arena_mapp_get(chunk, pageind)->prof_ctx = ctx; } -#endif -JEMALLOC_INLINE void -arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr) +JEMALLOC_ALWAYS_INLINE void * +arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache) +{ + tcache_t *tcache; + + assert(size != 0); + assert(size <= arena_maxclass); + + if (size <= SMALL_MAXCLASS) { + if (try_tcache && (tcache = tcache_get(true)) != NULL) + return (tcache_alloc_small(tcache, size, zero)); + else { + return (arena_malloc_small(choose_arena(arena), size, + zero)); + } + } else { + /* + * Initialize tcache after checking size in order to avoid + * infinite recursion during tcache initialization. + */ + if (try_tcache && size <= tcache_maxclass && (tcache = + tcache_get(true)) != NULL) + return (tcache_alloc_large(tcache, size, zero)); + else { + return (arena_malloc_large(choose_arena(arena), size, + zero)); + } + } +} + +/* Return the size of the allocation pointed to by ptr. */ +JEMALLOC_ALWAYS_INLINE size_t +arena_salloc(const void *ptr, bool demote) { - size_t pageind; - arena_chunk_map_t *mapelm; + size_t ret; + arena_chunk_t *chunk; + size_t pageind, binind; + + assert(ptr != NULL); + assert(CHUNK_ADDR2BASE(ptr) != ptr); + + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + assert(arena_mapbits_allocated_get(chunk, pageind) != 0); + binind = arena_mapbits_binind_get(chunk, pageind); + if (binind == BININD_INVALID || (config_prof && demote == false && + prof_promote && arena_mapbits_large_get(chunk, pageind) != 0)) { + /* + * Large allocation. In the common case (demote == true), and + * as this is an inline function, most callers will only end up + * looking at binind to determine that ptr is a small + * allocation. + */ + assert(((uintptr_t)ptr & PAGE_MASK) == 0); + ret = arena_mapbits_large_size_get(chunk, pageind); + assert(ret != 0); + assert(pageind + (ret>>LG_PAGE) <= chunk_npages); + assert(ret == PAGE || arena_mapbits_large_size_get(chunk, + pageind+(ret>>LG_PAGE)-1) == 0); + assert(binind == arena_mapbits_binind_get(chunk, + pageind+(ret>>LG_PAGE)-1)); + assert(arena_mapbits_dirty_get(chunk, pageind) == + arena_mapbits_dirty_get(chunk, pageind+(ret>>LG_PAGE)-1)); + } else { + /* + * Small allocation (possibly promoted to a large object due to + * prof_promote). + */ + assert(arena_mapbits_large_get(chunk, pageind) != 0 || + arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk, + pageind)) == binind); + ret = arena_bin_info[binind].reg_size; + } + + return (ret); +} + +JEMALLOC_ALWAYS_INLINE void +arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache) +{ + size_t pageind, mapbits; + tcache_t *tcache; assert(arena != NULL); - assert(arena->magic == ARENA_MAGIC); assert(chunk->arena == arena); assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapelm = &chunk->map[pageind-map_bias]; - assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) { + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + mapbits = arena_mapbits_get(chunk, pageind); + assert(arena_mapbits_allocated_get(chunk, pageind) != 0); + if ((mapbits & CHUNK_MAP_LARGE) == 0) { /* Small allocation. */ -#ifdef JEMALLOC_TCACHE - tcache_t *tcache; + if (try_tcache && (tcache = tcache_get(false)) != NULL) { + size_t binind; - if ((tcache = tcache_get()) != NULL) - tcache_dalloc_small(tcache, ptr); - else { -#endif - arena_run_t *run; - arena_bin_t *bin; - - run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapelm->bits >> - PAGE_SHIFT)) << PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - assert(((uintptr_t)ptr - ((uintptr_t)run + - (uintptr_t)run->bin->reg0_offset)) % - run->bin->reg_size == 0); - bin = run->bin; - malloc_mutex_lock(&bin->lock); - arena_dalloc_bin(arena, chunk, ptr, mapelm); - malloc_mutex_unlock(&bin->lock); -#ifdef JEMALLOC_TCACHE - } -#endif + binind = arena_ptr_small_binind_get(ptr, mapbits); + tcache_dalloc_small(tcache, ptr, binind); + } else + arena_dalloc_small(arena, chunk, ptr, pageind); } else { -#ifdef JEMALLOC_TCACHE - size_t size = mapelm->bits & ~PAGE_MASK; + size_t size = arena_mapbits_large_size_get(chunk, pageind); assert(((uintptr_t)ptr & PAGE_MASK) == 0); - if (size <= tcache_maxclass) { - tcache_t *tcache; - - if ((tcache = tcache_get()) != NULL) - tcache_dalloc_large(tcache, ptr, size); - else { - malloc_mutex_lock(&arena->lock); - arena_dalloc_large(arena, chunk, ptr); - malloc_mutex_unlock(&arena->lock); - } - } else { - malloc_mutex_lock(&arena->lock); + + if (try_tcache && size <= tcache_maxclass && (tcache = + tcache_get(false)) != NULL) { + tcache_dalloc_large(tcache, ptr, size); + } else arena_dalloc_large(arena, chunk, ptr); - malloc_mutex_unlock(&arena->lock); - } -#else - assert(((uintptr_t)ptr & PAGE_MASK) == 0); - malloc_mutex_lock(&arena->lock); - arena_dalloc_large(arena, chunk, ptr); - malloc_mutex_unlock(&arena->lock); -#endif } } +# endif /* JEMALLOC_ARENA_INLINE_B */ #endif #endif /* JEMALLOC_H_INLINES */ diff --git a/dep/jemalloc/include/jemalloc/internal/atomic.h b/dep/jemalloc/include/jemalloc/internal/atomic.h new file mode 100644 index 00000000000..11a7b47fe0f --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/atomic.h @@ -0,0 +1,304 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +#define atomic_read_uint64(p) atomic_add_uint64(p, 0) +#define atomic_read_uint32(p) atomic_add_uint32(p, 0) +#define atomic_read_z(p) atomic_add_z(p, 0) +#define atomic_read_u(p) atomic_add_u(p, 0) + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#ifndef JEMALLOC_ENABLE_INLINE +uint64_t atomic_add_uint64(uint64_t *p, uint64_t x); +uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x); +uint32_t atomic_add_uint32(uint32_t *p, uint32_t x); +uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x); +size_t atomic_add_z(size_t *p, size_t x); +size_t atomic_sub_z(size_t *p, size_t x); +unsigned atomic_add_u(unsigned *p, unsigned x); +unsigned atomic_sub_u(unsigned *p, unsigned x); +#endif + +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_)) +/******************************************************************************/ +/* 64-bit operations. */ +#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3) +# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + return (__sync_add_and_fetch(p, x)); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + return (__sync_sub_and_fetch(p, x)); +} +#elif (defined(_MSC_VER)) +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + return (InterlockedExchangeAdd64(p, x)); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + return (InterlockedExchangeAdd64(p, -((int64_t)x))); +} +#elif (defined(JEMALLOC_OSATOMIC)) +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + return (OSAtomicAdd64((int64_t)x, (int64_t *)p)); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p)); +} +# elif (defined(__amd64__) || defined(__x86_64__)) +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + asm volatile ( + "lock; xaddq %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + + return (x); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + x = (uint64_t)(-(int64_t)x); + asm volatile ( + "lock; xaddq %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + + return (x); +} +# elif (defined(JEMALLOC_ATOMIC9)) +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + /* + * atomic_fetchadd_64() doesn't exist, but we only ever use this + * function on LP64 systems, so atomic_fetchadd_long() will do. + */ + assert(sizeof(uint64_t) == sizeof(unsigned long)); + + return (atomic_fetchadd_long(p, (unsigned long)x) + x); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + assert(sizeof(uint64_t) == sizeof(unsigned long)); + + return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x); +} +# elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8)) +JEMALLOC_INLINE uint64_t +atomic_add_uint64(uint64_t *p, uint64_t x) +{ + + return (__sync_add_and_fetch(p, x)); +} + +JEMALLOC_INLINE uint64_t +atomic_sub_uint64(uint64_t *p, uint64_t x) +{ + + return (__sync_sub_and_fetch(p, x)); +} +# else +# error "Missing implementation for 64-bit atomic operations" +# endif +#endif + +/******************************************************************************/ +/* 32-bit operations. */ +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + return (__sync_add_and_fetch(p, x)); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + return (__sync_sub_and_fetch(p, x)); +} +#elif (defined(_MSC_VER)) +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + return (InterlockedExchangeAdd(p, x)); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + return (InterlockedExchangeAdd(p, -((int32_t)x))); +} +#elif (defined(JEMALLOC_OSATOMIC)) +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + return (OSAtomicAdd32((int32_t)x, (int32_t *)p)); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p)); +} +#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + asm volatile ( + "lock; xaddl %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + + return (x); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + x = (uint32_t)(-(int32_t)x); + asm volatile ( + "lock; xaddl %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + + return (x); +} +#elif (defined(JEMALLOC_ATOMIC9)) +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + return (atomic_fetchadd_32(p, x) + x); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x); +} +#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4)) +JEMALLOC_INLINE uint32_t +atomic_add_uint32(uint32_t *p, uint32_t x) +{ + + return (__sync_add_and_fetch(p, x)); +} + +JEMALLOC_INLINE uint32_t +atomic_sub_uint32(uint32_t *p, uint32_t x) +{ + + return (__sync_sub_and_fetch(p, x)); +} +#else +# error "Missing implementation for 32-bit atomic operations" +#endif + +/******************************************************************************/ +/* size_t operations. */ +JEMALLOC_INLINE size_t +atomic_add_z(size_t *p, size_t x) +{ + +#if (LG_SIZEOF_PTR == 3) + return ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); +#elif (LG_SIZEOF_PTR == 2) + return ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); +#endif +} + +JEMALLOC_INLINE size_t +atomic_sub_z(size_t *p, size_t x) +{ + +#if (LG_SIZEOF_PTR == 3) + return ((size_t)atomic_add_uint64((uint64_t *)p, + (uint64_t)-((int64_t)x))); +#elif (LG_SIZEOF_PTR == 2) + return ((size_t)atomic_add_uint32((uint32_t *)p, + (uint32_t)-((int32_t)x))); +#endif +} + +/******************************************************************************/ +/* unsigned operations. */ +JEMALLOC_INLINE unsigned +atomic_add_u(unsigned *p, unsigned x) +{ + +#if (LG_SIZEOF_INT == 3) + return ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); +#elif (LG_SIZEOF_INT == 2) + return ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); +#endif +} + +JEMALLOC_INLINE unsigned +atomic_sub_u(unsigned *p, unsigned x) +{ + +#if (LG_SIZEOF_INT == 3) + return ((unsigned)atomic_add_uint64((uint64_t *)p, + (uint64_t)-((int64_t)x))); +#elif (LG_SIZEOF_INT == 2) + return ((unsigned)atomic_add_uint32((uint32_t *)p, + (uint32_t)-((int32_t)x))); +#endif +} +/******************************************************************************/ +#endif + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/base.h b/dep/jemalloc/include/jemalloc/internal/base.h index e353f309bd2..9cf75ffb0b3 100644 --- a/dep/jemalloc/include/jemalloc/internal/base.h +++ b/dep/jemalloc/include/jemalloc/internal/base.h @@ -9,12 +9,14 @@ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -extern malloc_mutex_t base_mtx; - void *base_alloc(size_t size); +void *base_calloc(size_t number, size_t size); extent_node_t *base_node_alloc(void); void base_node_dealloc(extent_node_t *node); bool base_boot(void); +void base_prefork(void); +void base_postfork_parent(void); +void base_postfork_child(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/bitmap.h b/dep/jemalloc/include/jemalloc/internal/bitmap.h new file mode 100644 index 00000000000..605ebac58c1 --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/bitmap.h @@ -0,0 +1,184 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */ +#define LG_BITMAP_MAXBITS LG_RUN_MAXREGS + +typedef struct bitmap_level_s bitmap_level_t; +typedef struct bitmap_info_s bitmap_info_t; +typedef unsigned long bitmap_t; +#define LG_SIZEOF_BITMAP LG_SIZEOF_LONG + +/* Number of bits per group. */ +#define LG_BITMAP_GROUP_NBITS (LG_SIZEOF_BITMAP + 3) +#define BITMAP_GROUP_NBITS (ZU(1) << LG_BITMAP_GROUP_NBITS) +#define BITMAP_GROUP_NBITS_MASK (BITMAP_GROUP_NBITS-1) + +/* Maximum number of levels possible. */ +#define BITMAP_MAX_LEVELS \ + (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \ + + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP) + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +struct bitmap_level_s { + /* Offset of this level's groups within the array of groups. */ + size_t group_offset; +}; + +struct bitmap_info_s { + /* Logical number of bits in bitmap (stored at bottom level). */ + size_t nbits; + + /* Number of levels necessary for nbits. */ + unsigned nlevels; + + /* + * Only the first (nlevels+1) elements are used, and levels are ordered + * bottom to top (e.g. the bottom level is stored in levels[0]). + */ + bitmap_level_t levels[BITMAP_MAX_LEVELS+1]; +}; + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +void bitmap_info_init(bitmap_info_t *binfo, size_t nbits); +size_t bitmap_info_ngroups(const bitmap_info_t *binfo); +size_t bitmap_size(size_t nbits); +void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#ifndef JEMALLOC_ENABLE_INLINE +bool bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo); +bool bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); +void bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); +size_t bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo); +void bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); +#endif + +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_)) +JEMALLOC_INLINE bool +bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo) +{ + unsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1; + bitmap_t rg = bitmap[rgoff]; + /* The bitmap is full iff the root group is 0. */ + return (rg == 0); +} + +JEMALLOC_INLINE bool +bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) +{ + size_t goff; + bitmap_t g; + + assert(bit < binfo->nbits); + goff = bit >> LG_BITMAP_GROUP_NBITS; + g = bitmap[goff]; + return (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))); +} + +JEMALLOC_INLINE void +bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) +{ + size_t goff; + bitmap_t *gp; + bitmap_t g; + + assert(bit < binfo->nbits); + assert(bitmap_get(bitmap, binfo, bit) == false); + goff = bit >> LG_BITMAP_GROUP_NBITS; + gp = &bitmap[goff]; + g = *gp; + assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))); + g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + *gp = g; + assert(bitmap_get(bitmap, binfo, bit)); + /* Propagate group state transitions up the tree. */ + if (g == 0) { + unsigned i; + for (i = 1; i < binfo->nlevels; i++) { + bit = goff; + goff = bit >> LG_BITMAP_GROUP_NBITS; + gp = &bitmap[binfo->levels[i].group_offset + goff]; + g = *gp; + assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))); + g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + *gp = g; + if (g != 0) + break; + } + } +} + +/* sfu: set first unset. */ +JEMALLOC_INLINE size_t +bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo) +{ + size_t bit; + bitmap_t g; + unsigned i; + + assert(bitmap_full(bitmap, binfo) == false); + + i = binfo->nlevels - 1; + g = bitmap[binfo->levels[i].group_offset]; + bit = ffsl(g) - 1; + while (i > 0) { + i--; + g = bitmap[binfo->levels[i].group_offset + bit]; + bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1); + } + + bitmap_set(bitmap, binfo, bit); + return (bit); +} + +JEMALLOC_INLINE void +bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) +{ + size_t goff; + bitmap_t *gp; + bitmap_t g; + bool propagate; + + assert(bit < binfo->nbits); + assert(bitmap_get(bitmap, binfo, bit)); + goff = bit >> LG_BITMAP_GROUP_NBITS; + gp = &bitmap[goff]; + g = *gp; + propagate = (g == 0); + assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0); + g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + *gp = g; + assert(bitmap_get(bitmap, binfo, bit) == false); + /* Propagate group state transitions up the tree. */ + if (propagate) { + unsigned i; + for (i = 1; i < binfo->nlevels; i++) { + bit = goff; + goff = bit >> LG_BITMAP_GROUP_NBITS; + gp = &bitmap[binfo->levels[i].group_offset + goff]; + g = *gp; + propagate = (g == 0); + assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) + == 0); + g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + *gp = g; + if (propagate == false) + break; + } + } +} + +#endif + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/chunk.h b/dep/jemalloc/include/jemalloc/internal/chunk.h index a60f0ad7498..87d8700dac8 100644 --- a/dep/jemalloc/include/jemalloc/internal/chunk.h +++ b/dep/jemalloc/include/jemalloc/internal/chunk.h @@ -28,20 +28,14 @@ #ifdef JEMALLOC_H_EXTERNS extern size_t opt_lg_chunk; -#ifdef JEMALLOC_SWAP -extern bool opt_overcommit; -#endif +extern const char *opt_dss; -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) /* Protects stats_chunks; currently not used for any other purpose. */ extern malloc_mutex_t chunks_mtx; /* Chunk statistics. */ extern chunk_stats_t stats_chunks; -#endif -#ifdef JEMALLOC_IVSALLOC extern rtree_t *chunks_rtree; -#endif extern size_t chunksize; extern size_t chunksize_mask; /* (chunksize - 1). */ @@ -49,9 +43,14 @@ extern size_t chunk_npages; extern size_t map_bias; /* Number of arena chunk header pages. */ extern size_t arena_maxclass; /* Max size class for arenas. */ -void *chunk_alloc(size_t size, bool base, bool *zero); -void chunk_dealloc(void *chunk, size_t size); +void *chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, + dss_prec_t dss_prec); +void chunk_unmap(void *chunk, size_t size); +void chunk_dealloc(void *chunk, size_t size, bool unmap); bool chunk_boot(void); +void chunk_prefork(void); +void chunk_postfork_parent(void); +void chunk_postfork_child(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ @@ -60,6 +59,5 @@ bool chunk_boot(void); #endif /* JEMALLOC_H_INLINES */ /******************************************************************************/ -#include "jemalloc/internal/chunk_swap.h" #include "jemalloc/internal/chunk_dss.h" #include "jemalloc/internal/chunk_mmap.h" diff --git a/dep/jemalloc/include/jemalloc/internal/chunk_dss.h b/dep/jemalloc/include/jemalloc/internal/chunk_dss.h index 6f005222181..6585f071bbe 100644 --- a/dep/jemalloc/include/jemalloc/internal/chunk_dss.h +++ b/dep/jemalloc/include/jemalloc/internal/chunk_dss.h @@ -1,25 +1,34 @@ -#ifdef JEMALLOC_DSS /******************************************************************************/ #ifdef JEMALLOC_H_TYPES +typedef enum { + dss_prec_disabled = 0, + dss_prec_primary = 1, + dss_prec_secondary = 2, + + dss_prec_limit = 3 +} dss_prec_t ; +#define DSS_PREC_DEFAULT dss_prec_secondary +#define DSS_DEFAULT "secondary" + #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS +extern const char *dss_prec_names[]; + #endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -/* - * Protects sbrk() calls. This avoids malloc races among threads, though it - * does not protect against races with threads that call sbrk() directly. - */ -extern malloc_mutex_t dss_mtx; - -void *chunk_alloc_dss(size_t size, bool *zero); +dss_prec_t chunk_dss_prec_get(void); +bool chunk_dss_prec_set(dss_prec_t dss_prec); +void *chunk_alloc_dss(size_t size, size_t alignment, bool *zero); bool chunk_in_dss(void *chunk); -bool chunk_dealloc_dss(void *chunk, size_t size); bool chunk_dss_boot(void); +void chunk_dss_prefork(void); +void chunk_dss_postfork_parent(void); +void chunk_dss_postfork_child(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ @@ -27,4 +36,3 @@ bool chunk_dss_boot(void); #endif /* JEMALLOC_H_INLINES */ /******************************************************************************/ -#endif /* JEMALLOC_DSS */ diff --git a/dep/jemalloc/include/jemalloc/internal/chunk_mmap.h b/dep/jemalloc/include/jemalloc/internal/chunk_mmap.h index 07b50a4dc37..f24abac7538 100644 --- a/dep/jemalloc/include/jemalloc/internal/chunk_mmap.h +++ b/dep/jemalloc/include/jemalloc/internal/chunk_mmap.h @@ -9,11 +9,10 @@ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -void *chunk_alloc_mmap(size_t size); -void *chunk_alloc_mmap_noreserve(size_t size); -void chunk_dealloc_mmap(void *chunk, size_t size); +bool pages_purge(void *addr, size_t length); -bool chunk_mmap_boot(void); +void *chunk_alloc_mmap(size_t size, size_t alignment, bool *zero); +bool chunk_dealloc_mmap(void *chunk, size_t size); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/chunk_swap.h b/dep/jemalloc/include/jemalloc/internal/chunk_swap.h deleted file mode 100644 index 9faa739f713..00000000000 --- a/dep/jemalloc/include/jemalloc/internal/chunk_swap.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifdef JEMALLOC_SWAP -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -extern malloc_mutex_t swap_mtx; -extern bool swap_enabled; -extern bool swap_prezeroed; -extern size_t swap_nfds; -extern int *swap_fds; -#ifdef JEMALLOC_STATS -extern size_t swap_avail; -#endif - -void *chunk_alloc_swap(size_t size, bool *zero); -bool chunk_in_swap(void *chunk); -bool chunk_dealloc_swap(void *chunk, size_t size); -bool chunk_swap_enable(const int *fds, unsigned nfds, bool prezeroed); -bool chunk_swap_boot(void); - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ -#endif /* JEMALLOC_SWAP */ diff --git a/dep/jemalloc/include/jemalloc/internal/ckh.h b/dep/jemalloc/include/jemalloc/internal/ckh.h index d4e391b6360..50c39ed9581 100644 --- a/dep/jemalloc/include/jemalloc/internal/ckh.h +++ b/dep/jemalloc/include/jemalloc/internal/ckh.h @@ -5,7 +5,7 @@ typedef struct ckh_s ckh_t; typedef struct ckhc_s ckhc_t; /* Typedefs to allow easy function pointer passing. */ -typedef void ckh_hash_t (const void *, unsigned, size_t *, size_t *); +typedef void ckh_hash_t (const void *, size_t[2]); typedef bool ckh_keycomp_t (const void *, const void *); /* Maintain counters used to get an idea of performance. */ @@ -30,11 +30,6 @@ struct ckhc_s { }; struct ckh_s { -#ifdef JEMALLOC_DEBUG -#define CKH_MAGIG 0x3af2489d - uint32_t magic; -#endif - #ifdef CKH_COUNT /* Counters used to get an idea of performance. */ uint64_t ngrows; @@ -47,7 +42,7 @@ struct ckh_s { /* Used for pseudo-random number generation. */ #define CKH_A 1103515241 #define CKH_C 12347 - uint32_t prn_state; + uint32_t prng_state; /* Total number of items. */ size_t count; @@ -80,11 +75,9 @@ bool ckh_insert(ckh_t *ckh, const void *key, const void *data); bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data); bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data); -void ckh_string_hash(const void *key, unsigned minbits, size_t *hash1, - size_t *hash2); +void ckh_string_hash(const void *key, size_t r_hash[2]); bool ckh_string_keycomp(const void *k1, const void *k2); -void ckh_pointer_hash(const void *key, unsigned minbits, size_t *hash1, - size_t *hash2); +void ckh_pointer_hash(const void *key, size_t r_hash[2]); bool ckh_pointer_keycomp(const void *k1, const void *k2); #endif /* JEMALLOC_H_EXTERNS */ diff --git a/dep/jemalloc/include/jemalloc/internal/ctl.h b/dep/jemalloc/include/jemalloc/internal/ctl.h index 8776ad135a7..0ffecc5f2a2 100644 --- a/dep/jemalloc/include/jemalloc/internal/ctl.h +++ b/dep/jemalloc/include/jemalloc/internal/ctl.h @@ -2,6 +2,8 @@ #ifdef JEMALLOC_H_TYPES typedef struct ctl_node_s ctl_node_t; +typedef struct ctl_named_node_s ctl_named_node_t; +typedef struct ctl_indexed_node_s ctl_indexed_node_t; typedef struct ctl_arena_stats_s ctl_arena_stats_t; typedef struct ctl_stats_s ctl_stats_t; @@ -11,27 +13,29 @@ typedef struct ctl_stats_s ctl_stats_t; struct ctl_node_s { bool named; - union { - struct { - const char *name; - /* If (nchildren == 0), this is a terminal node. */ - unsigned nchildren; - const ctl_node_t *children; - } named; - struct { - const ctl_node_t *(*index)(const size_t *, size_t, - size_t); - } indexed; - } u; - int (*ctl)(const size_t *, size_t, void *, size_t *, void *, - size_t); +}; + +struct ctl_named_node_s { + struct ctl_node_s node; + const char *name; + /* If (nchildren == 0), this is a terminal node. */ + unsigned nchildren; + const ctl_node_t *children; + int (*ctl)(const size_t *, size_t, void *, size_t *, + void *, size_t); +}; + +struct ctl_indexed_node_s { + struct ctl_node_s node; + const ctl_named_node_t *(*index)(const size_t *, size_t, size_t); }; struct ctl_arena_stats_s { bool initialized; + unsigned nthreads; + const char *dss; size_t pactive; size_t pdirty; -#ifdef JEMALLOC_STATS arena_stats_t astats; /* Aggregate stats for small size classes, based on bin stats. */ @@ -40,13 +44,11 @@ struct ctl_arena_stats_s { uint64_t ndalloc_small; uint64_t nrequests_small; - malloc_bin_stats_t *bstats; /* nbins elements. */ + malloc_bin_stats_t bstats[NBINS]; malloc_large_stats_t *lstats; /* nlclasses elements. */ -#endif }; struct ctl_stats_s { -#ifdef JEMALLOC_STATS size_t allocated; size_t active; size_t mapped; @@ -60,11 +62,8 @@ struct ctl_stats_s { uint64_t nmalloc; /* huge_nmalloc */ uint64_t ndalloc; /* huge_ndalloc */ } huge; -#endif + unsigned narenas; ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */ -#ifdef JEMALLOC_SWAP - size_t swap_avail; -#endif }; #endif /* JEMALLOC_H_STRUCTS */ @@ -78,29 +77,30 @@ int ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp); int ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); bool ctl_boot(void); +void ctl_prefork(void); +void ctl_postfork_parent(void); +void ctl_postfork_child(void); #define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ - if (JEMALLOC_P(mallctl)(name, oldp, oldlenp, newp, newlen) \ + if (je_mallctl(name, oldp, oldlenp, newp, newlen) \ != 0) { \ - malloc_write("<jemalloc>: Failure in xmallctl(\""); \ - malloc_write(name); \ - malloc_write("\", ...)\n"); \ + malloc_printf( \ + "<jemalloc>: Failure in xmallctl(\"%s\", ...)\n", \ + name); \ abort(); \ } \ } while (0) #define xmallctlnametomib(name, mibp, miblenp) do { \ - if (JEMALLOC_P(mallctlnametomib)(name, mibp, miblenp) != 0) { \ - malloc_write( \ - "<jemalloc>: Failure in xmallctlnametomib(\""); \ - malloc_write(name); \ - malloc_write("\", ...)\n"); \ + if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \ + malloc_printf("<jemalloc>: Failure in " \ + "xmallctlnametomib(\"%s\", ...)\n", name); \ abort(); \ } \ } while (0) #define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \ - if (JEMALLOC_P(mallctlbymib)(mib, miblen, oldp, oldlenp, newp, \ + if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \ newlen) != 0) { \ malloc_write( \ "<jemalloc>: Failure in xmallctlbymib()\n"); \ diff --git a/dep/jemalloc/include/jemalloc/internal/extent.h b/dep/jemalloc/include/jemalloc/internal/extent.h index 6fe9702b5f6..ba95ca816bd 100644 --- a/dep/jemalloc/include/jemalloc/internal/extent.h +++ b/dep/jemalloc/include/jemalloc/internal/extent.h @@ -9,24 +9,23 @@ typedef struct extent_node_s extent_node_t; /* Tree of extents. */ struct extent_node_s { -#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS)) /* Linkage for the size/address-ordered tree. */ rb_node(extent_node_t) link_szad; -#endif /* Linkage for the address-ordered tree. */ rb_node(extent_node_t) link_ad; -#ifdef JEMALLOC_PROF /* Profile counters, used for huge objects. */ prof_ctx_t *prof_ctx; -#endif /* Pointer to the extent that this tree node is responsible for. */ void *addr; /* Total region size. */ size_t size; + + /* True if zero-filled; used by chunk recycling code. */ + bool zeroed; }; typedef rb_tree(extent_node_t) extent_tree_t; @@ -34,9 +33,7 @@ typedef rb_tree(extent_node_t) extent_tree_t; /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS)) rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t) -#endif rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t) diff --git a/dep/jemalloc/include/jemalloc/internal/hash.h b/dep/jemalloc/include/jemalloc/internal/hash.h index d12cdb8359f..56ecc793b36 100644 --- a/dep/jemalloc/include/jemalloc/internal/hash.h +++ b/dep/jemalloc/include/jemalloc/internal/hash.h @@ -1,3 +1,8 @@ +/* + * The following hash function is based on MurmurHash3, placed into the public + * domain by Austin Appleby. See http://code.google.com/p/smhasher/ for + * details. + */ /******************************************************************************/ #ifdef JEMALLOC_H_TYPES @@ -14,55 +19,311 @@ #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE -uint64_t hash(const void *key, size_t len, uint64_t seed); +void hash(const void *key, size_t len, const uint32_t seed, + size_t r_hash[2]); #endif -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(HASH_C_)) -/* - * The following hash function is based on MurmurHash64A(), placed into the - * public domain by Austin Appleby. See http://murmurhash.googlepages.com/ for - * details. - */ +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_)) +/******************************************************************************/ +/* Internal implementation. */ +JEMALLOC_INLINE uint32_t +hash_rotl_32(uint32_t x, int8_t r) +{ + + return (x << r) | (x >> (32 - r)); +} + +JEMALLOC_INLINE uint64_t +hash_rotl_64(uint64_t x, int8_t r) +{ + return (x << r) | (x >> (64 - r)); +} + +JEMALLOC_INLINE uint32_t +hash_get_block_32(const uint32_t *p, int i) +{ + + return p[i]; +} + +JEMALLOC_INLINE uint64_t +hash_get_block_64(const uint64_t *p, int i) +{ + + return p[i]; +} + +JEMALLOC_INLINE uint32_t +hash_fmix_32(uint32_t h) +{ + + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + JEMALLOC_INLINE uint64_t -hash(const void *key, size_t len, uint64_t seed) +hash_fmix_64(uint64_t k) { - const uint64_t m = 0xc6a4a7935bd1e995; - const int r = 47; - uint64_t h = seed ^ (len * m); - const uint64_t *data = (const uint64_t *)key; - const uint64_t *end = data + (len/8); - const unsigned char *data2; - assert(((uintptr_t)key & 0x7) == 0); + k ^= k >> 33; + k *= QU(0xff51afd7ed558ccdLLU); + k ^= k >> 33; + k *= QU(0xc4ceb9fe1a85ec53LLU); + k ^= k >> 33; + + return k; +} + +JEMALLOC_INLINE uint32_t +hash_x86_32(const void *key, int len, uint32_t seed) +{ + const uint8_t *data = (const uint8_t *) key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - while(data != end) { - uint64_t k = *data++; + /* body */ + { + const uint32_t *blocks = (const uint32_t *) (data + nblocks*4); + int i; - k *= m; - k ^= k >> r; - k *= m; + for (i = -nblocks; i; i++) { + uint32_t k1 = hash_get_block_32(blocks, i); - h ^= k; - h *= m; + k1 *= c1; + k1 = hash_rotl_32(k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = hash_rotl_32(h1, 13); + h1 = h1*5 + 0xe6546b64; + } } - data2 = (const unsigned char *)data; - switch(len & 7) { - case 7: h ^= ((uint64_t)(data2[6])) << 48; - case 6: h ^= ((uint64_t)(data2[5])) << 40; - case 5: h ^= ((uint64_t)(data2[4])) << 32; - case 4: h ^= ((uint64_t)(data2[3])) << 24; - case 3: h ^= ((uint64_t)(data2[2])) << 16; - case 2: h ^= ((uint64_t)(data2[1])) << 8; - case 1: h ^= ((uint64_t)(data2[0])); - h *= m; + /* tail */ + { + const uint8_t *tail = (const uint8_t *) (data + nblocks*4); + + uint32_t k1 = 0; + + switch (len & 3) { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15); + k1 *= c2; h1 ^= k1; + } } - h ^= h >> r; - h *= m; - h ^= h >> r; + /* finalization */ + h1 ^= len; - return h; + h1 = hash_fmix_32(h1); + + return h1; +} + +UNUSED JEMALLOC_INLINE void +hash_x86_128(const void *key, const int len, uint32_t seed, + uint64_t r_out[2]) +{ + const uint8_t * data = (const uint8_t *) key; + const int nblocks = len / 16; + + uint32_t h1 = seed; + uint32_t h2 = seed; + uint32_t h3 = seed; + uint32_t h4 = seed; + + const uint32_t c1 = 0x239b961b; + const uint32_t c2 = 0xab0e9789; + const uint32_t c3 = 0x38b34ae5; + const uint32_t c4 = 0xa1e38b93; + + /* body */ + { + const uint32_t *blocks = (const uint32_t *) (data + nblocks*16); + int i; + + for (i = -nblocks; i; i++) { + uint32_t k1 = hash_get_block_32(blocks, i*4 + 0); + uint32_t k2 = hash_get_block_32(blocks, i*4 + 1); + uint32_t k3 = hash_get_block_32(blocks, i*4 + 2); + uint32_t k4 = hash_get_block_32(blocks, i*4 + 3); + + k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; + + h1 = hash_rotl_32(h1, 19); h1 += h2; + h1 = h1*5 + 0x561ccd1b; + + k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2; + + h2 = hash_rotl_32(h2, 17); h2 += h3; + h2 = h2*5 + 0x0bcaa747; + + k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3; + + h3 = hash_rotl_32(h3, 15); h3 += h4; + h3 = h3*5 + 0x96cd1c35; + + k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4; + + h4 = hash_rotl_32(h4, 13); h4 += h1; + h4 = h4*5 + 0x32ac3b17; + } + } + + /* tail */ + { + const uint8_t *tail = (const uint8_t *) (data + nblocks*16); + uint32_t k1 = 0; + uint32_t k2 = 0; + uint32_t k3 = 0; + uint32_t k4 = 0; + + switch (len & 15) { + case 15: k4 ^= tail[14] << 16; + case 14: k4 ^= tail[13] << 8; + case 13: k4 ^= tail[12] << 0; + k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4; + + case 12: k3 ^= tail[11] << 24; + case 11: k3 ^= tail[10] << 16; + case 10: k3 ^= tail[ 9] << 8; + case 9: k3 ^= tail[ 8] << 0; + k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3; + + case 8: k2 ^= tail[ 7] << 24; + case 7: k2 ^= tail[ 6] << 16; + case 6: k2 ^= tail[ 5] << 8; + case 5: k2 ^= tail[ 4] << 0; + k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2; + + case 4: k1 ^= tail[ 3] << 24; + case 3: k1 ^= tail[ 2] << 16; + case 2: k1 ^= tail[ 1] << 8; + case 1: k1 ^= tail[ 0] << 0; + k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; + } + } + + /* finalization */ + h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = hash_fmix_32(h1); + h2 = hash_fmix_32(h2); + h3 = hash_fmix_32(h3); + h4 = hash_fmix_32(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + r_out[0] = (((uint64_t) h2) << 32) | h1; + r_out[1] = (((uint64_t) h4) << 32) | h3; +} + +UNUSED JEMALLOC_INLINE void +hash_x64_128(const void *key, const int len, const uint32_t seed, + uint64_t r_out[2]) +{ + const uint8_t *data = (const uint8_t *) key; + const int nblocks = len / 16; + + uint64_t h1 = seed; + uint64_t h2 = seed; + + const uint64_t c1 = QU(0x87c37b91114253d5LLU); + const uint64_t c2 = QU(0x4cf5ad432745937fLLU); + + /* body */ + { + const uint64_t *blocks = (const uint64_t *) (data); + int i; + + for (i = 0; i < nblocks; i++) { + uint64_t k1 = hash_get_block_64(blocks, i*2 + 0); + uint64_t k2 = hash_get_block_64(blocks, i*2 + 1); + + k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1; + + h1 = hash_rotl_64(h1, 27); h1 += h2; + h1 = h1*5 + 0x52dce729; + + k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2; + + h2 = hash_rotl_64(h2, 31); h2 += h1; + h2 = h2*5 + 0x38495ab5; + } + } + + /* tail */ + { + const uint8_t *tail = (const uint8_t*)(data + nblocks*16); + uint64_t k1 = 0; + uint64_t k2 = 0; + + switch (len & 15) { + case 15: k2 ^= ((uint64_t)(tail[14])) << 48; + case 14: k2 ^= ((uint64_t)(tail[13])) << 40; + case 13: k2 ^= ((uint64_t)(tail[12])) << 32; + case 12: k2 ^= ((uint64_t)(tail[11])) << 24; + case 11: k2 ^= ((uint64_t)(tail[10])) << 16; + case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; + case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0; + k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; + case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; + case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; + case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; + case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; + case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; + case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; + case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0; + k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1; + } + } + + /* finalization */ + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = hash_fmix_64(h1); + h2 = hash_fmix_64(h2); + + h1 += h2; + h2 += h1; + + r_out[0] = h1; + r_out[1] = h2; +} + + +/******************************************************************************/ +/* API. */ +JEMALLOC_INLINE void +hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) +{ +#if (LG_SIZEOF_PTR == 3) + hash_x64_128(key, len, seed, (uint64_t *)r_hash); +#else + uint64_t hashes[2]; + hash_x86_128(key, len, seed, hashes); + r_hash[0] = (size_t)hashes[0]; + r_hash[1] = (size_t)hashes[1]; +#endif } #endif diff --git a/dep/jemalloc/include/jemalloc/internal/huge.h b/dep/jemalloc/include/jemalloc/internal/huge.h index 66544cf8d97..d987d370767 100644 --- a/dep/jemalloc/include/jemalloc/internal/huge.h +++ b/dep/jemalloc/include/jemalloc/internal/huge.h @@ -9,12 +9,10 @@ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS -#ifdef JEMALLOC_STATS /* Huge allocation statistics. */ extern uint64_t huge_nmalloc; extern uint64_t huge_ndalloc; extern size_t huge_allocated; -#endif /* Protects chunk-related data structures. */ extern malloc_mutex_t huge_mtx; @@ -24,14 +22,15 @@ void *huge_palloc(size_t size, size_t alignment, bool zero); void *huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra); void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero); + size_t alignment, bool zero, bool try_tcache_dalloc); void huge_dalloc(void *ptr, bool unmap); size_t huge_salloc(const void *ptr); -#ifdef JEMALLOC_PROF prof_ctx_t *huge_prof_ctx_get(const void *ptr); void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx); -#endif bool huge_boot(void); +void huge_prefork(void); +void huge_postfork_parent(void); +void huge_postfork_child(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/jemalloc_internal.h b/dep/jemalloc/include/jemalloc/internal/jemalloc_internal.h index 611f0c665a1..80045bda4bd 100644 --- a/dep/jemalloc/include/jemalloc/internal/jemalloc_internal.h +++ b/dep/jemalloc/include/jemalloc/internal/jemalloc_internal.h @@ -1,17 +1,33 @@ -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/time.h> +#ifndef JEMALLOC_INTERNAL_H +#define JEMALLOC_INTERNAL_H +#include <math.h> +#ifdef _WIN32 +# include <windows.h> +# define ENOENT ERROR_PATH_NOT_FOUND +# define EINVAL ERROR_BAD_ARGUMENTS +# define EAGAIN ERROR_OUTOFMEMORY +# define EPERM ERROR_WRITE_FAULT +# define EFAULT ERROR_INVALID_ADDRESS +# define ENOMEM ERROR_NOT_ENOUGH_MEMORY +# undef ERANGE +# define ERANGE ERROR_INVALID_DATA +#else +# include <sys/param.h> +# include <sys/mman.h> +# include <sys/syscall.h> +# if !defined(SYS_write) && defined(__NR_write) +# define SYS_write __NR_write +# endif +# include <sys/uio.h> +# include <pthread.h> +# include <errno.h> +#endif #include <sys/types.h> -#include <sys/sysctl.h> -#include <sys/uio.h> -#include <errno.h> #include <limits.h> #ifndef SIZE_T_MAX # define SIZE_T_MAX SIZE_MAX #endif -#include <pthread.h> -#include <sched.h> #include <stdarg.h> #include <stdbool.h> #include <stdio.h> @@ -25,14 +41,160 @@ #include <string.h> #include <strings.h> #include <ctype.h> -#include <unistd.h> +#ifdef _MSC_VER +# include <io.h> +typedef intptr_t ssize_t; +# define PATH_MAX 1024 +# define STDERR_FILENO 2 +# define __func__ __FUNCTION__ +/* Disable warnings about deprecated system functions */ +# pragma warning(disable: 4996) +#else +# include <unistd.h> +#endif #include <fcntl.h> -#include <pthread.h> -#include <math.h> -#define JEMALLOC_MANGLE +#define JEMALLOC_NO_DEMANGLE #include "../jemalloc.h" +#ifdef JEMALLOC_UTRACE +#include <sys/ktrace.h> +#endif + +#ifdef JEMALLOC_VALGRIND +#include <valgrind/valgrind.h> +#include <valgrind/memcheck.h> +#endif + +#include "jemalloc/internal/private_namespace.h" + +#ifdef JEMALLOC_CC_SILENCE +#define UNUSED JEMALLOC_ATTR(unused) +#else +#define UNUSED +#endif + +static const bool config_debug = +#ifdef JEMALLOC_DEBUG + true +#else + false +#endif + ; +static const bool config_dss = +#ifdef JEMALLOC_DSS + true +#else + false +#endif + ; +static const bool config_fill = +#ifdef JEMALLOC_FILL + true +#else + false +#endif + ; +static const bool config_lazy_lock = +#ifdef JEMALLOC_LAZY_LOCK + true +#else + false +#endif + ; +static const bool config_prof = +#ifdef JEMALLOC_PROF + true +#else + false +#endif + ; +static const bool config_prof_libgcc = +#ifdef JEMALLOC_PROF_LIBGCC + true +#else + false +#endif + ; +static const bool config_prof_libunwind = +#ifdef JEMALLOC_PROF_LIBUNWIND + true +#else + false +#endif + ; +static const bool config_mremap = +#ifdef JEMALLOC_MREMAP + true +#else + false +#endif + ; +static const bool config_munmap = +#ifdef JEMALLOC_MUNMAP + true +#else + false +#endif + ; +static const bool config_stats = +#ifdef JEMALLOC_STATS + true +#else + false +#endif + ; +static const bool config_tcache = +#ifdef JEMALLOC_TCACHE + true +#else + false +#endif + ; +static const bool config_tls = +#ifdef JEMALLOC_TLS + true +#else + false +#endif + ; +static const bool config_utrace = +#ifdef JEMALLOC_UTRACE + true +#else + false +#endif + ; +static const bool config_valgrind = +#ifdef JEMALLOC_VALGRIND + true +#else + false +#endif + ; +static const bool config_xmalloc = +#ifdef JEMALLOC_XMALLOC + true +#else + false +#endif + ; +static const bool config_ivsalloc = +#ifdef JEMALLOC_IVSALLOC + true +#else + false +#endif + ; + +#ifdef JEMALLOC_ATOMIC9 +#include <machine/atomic.h> +#endif + +#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN)) +#include <libkern/OSAtomic.h> +#endif + #ifdef JEMALLOC_ZONE #include <mach/mach_error.h> #include <mach/mach_init.h> @@ -40,40 +202,11 @@ #include <malloc/malloc.h> #endif -#ifdef JEMALLOC_LAZY_LOCK -#include <dlfcn.h> -#endif - #define RB_COMPACT #include "jemalloc/internal/rb.h" #include "jemalloc/internal/qr.h" #include "jemalloc/internal/ql.h" -extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s); - -/* - * Define a custom assert() in order to reduce the chances of deadlock during - * assertion failure. - */ -#ifdef JEMALLOC_DEBUG -# define assert(e) do { \ - if (!(e)) { \ - char line_buf[UMAX2S_BUFSIZE]; \ - malloc_write("<jemalloc>: "); \ - malloc_write(__FILE__); \ - malloc_write(":"); \ - malloc_write(u2s(__LINE__, 10, line_buf)); \ - malloc_write(": Failed assertion: "); \ - malloc_write("\""); \ - malloc_write(#e); \ - malloc_write("\"\n"); \ - abort(); \ - } \ -} while (0) -#else -#define assert(e) -#endif - /* * jemalloc can conceptually be broken into components (arena, tcache, etc.), * but there are circular dependencies that cannot be broken without @@ -93,6 +226,7 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s); #define ALLOCM_LG_ALIGN_MASK ((int)0x3f) #define ZU(z) ((size_t)z) +#define QU(q) ((uint64_t)q) #ifndef __DECONST # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) @@ -100,43 +234,71 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s); #ifdef JEMALLOC_DEBUG /* Disable inlining to make debugging easier. */ +# define JEMALLOC_ALWAYS_INLINE # define JEMALLOC_INLINE # define inline #else # define JEMALLOC_ENABLE_INLINE +# ifdef JEMALLOC_HAVE_ATTR +# define JEMALLOC_ALWAYS_INLINE \ + static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline) +# else +# define JEMALLOC_ALWAYS_INLINE static inline +# endif # define JEMALLOC_INLINE static inline +# ifdef _MSC_VER +# define inline _inline +# endif #endif -/* Size of stack-allocated buffer passed to buferror(). */ -#define BUFERROR_BUF 64 +/* Smallest size class to support. */ +#define LG_TINY_MIN 3 +#define TINY_MIN (1U << LG_TINY_MIN) -/* Minimum alignment of allocations is 2^LG_QUANTUM bytes. */ -#ifdef __i386__ -# define LG_QUANTUM 4 -#endif -#ifdef __ia64__ -# define LG_QUANTUM 4 -#endif -#ifdef __alpha__ -# define LG_QUANTUM 4 -#endif -#ifdef __sparc64__ -# define LG_QUANTUM 4 -#endif -#if (defined(__amd64__) || defined(__x86_64__)) -# define LG_QUANTUM 4 -#endif -#ifdef __arm__ -# define LG_QUANTUM 3 -#endif -#ifdef __mips__ -# define LG_QUANTUM 3 -#endif -#ifdef __powerpc__ -# define LG_QUANTUM 4 -#endif -#ifdef __s390x__ -# define LG_QUANTUM 4 +/* + * Minimum alignment of allocations is 2^LG_QUANTUM bytes (ignoring tiny size + * classes). + */ +#ifndef LG_QUANTUM +# if (defined(__i386__) || defined(_M_IX86)) +# define LG_QUANTUM 4 +# endif +# ifdef __ia64__ +# define LG_QUANTUM 4 +# endif +# ifdef __alpha__ +# define LG_QUANTUM 4 +# endif +# ifdef __sparc64__ +# define LG_QUANTUM 4 +# endif +# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)) +# define LG_QUANTUM 4 +# endif +# ifdef __arm__ +# define LG_QUANTUM 3 +# endif +# ifdef __hppa__ +# define LG_QUANTUM 4 +# endif +# ifdef __mips__ +# define LG_QUANTUM 3 +# endif +# ifdef __powerpc__ +# define LG_QUANTUM 4 +# endif +# ifdef __s390__ +# define LG_QUANTUM 4 +# endif +# ifdef __SH4__ +# define LG_QUANTUM 4 +# endif +# ifdef __tile__ +# define LG_QUANTUM 4 +# endif +# ifndef LG_QUANTUM +# error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS" +# endif #endif #define QUANTUM ((size_t)(1U << LG_QUANTUM)) @@ -146,87 +308,189 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s); #define QUANTUM_CEILING(a) \ (((a) + QUANTUM_MASK) & ~QUANTUM_MASK) +#define LONG ((size_t)(1U << LG_SIZEOF_LONG)) +#define LONG_MASK (LONG - 1) + +/* Return the smallest long multiple that is >= a. */ +#define LONG_CEILING(a) \ + (((a) + LONG_MASK) & ~LONG_MASK) + #define SIZEOF_PTR (1U << LG_SIZEOF_PTR) +#define PTR_MASK (SIZEOF_PTR - 1) -/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */ -#if (!defined(PIC) && !defined(NO_TLS)) -# define NO_TLS -#endif +/* Return the smallest (void *) multiple that is >= a. */ +#define PTR_CEILING(a) \ + (((a) + PTR_MASK) & ~PTR_MASK) /* * Maximum size of L1 cache line. This is used to avoid cache line aliasing. * In addition, this controls the spacing of cacheline-spaced size classes. + * + * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can + * only handle raw constants. */ #define LG_CACHELINE 6 -#define CACHELINE ((size_t)(1U << LG_CACHELINE)) +#define CACHELINE 64 #define CACHELINE_MASK (CACHELINE - 1) /* Return the smallest cacheline multiple that is >= s. */ #define CACHELINE_CEILING(s) \ (((s) + CACHELINE_MASK) & ~CACHELINE_MASK) -/* - * Page size. STATIC_PAGE_SHIFT is determined by the configure script. If - * DYNAMIC_PAGE_SHIFT is enabled, only use the STATIC_PAGE_* macros where - * compile-time values are required for the purposes of defining data - * structures. - */ -#define STATIC_PAGE_SIZE ((size_t)(1U << STATIC_PAGE_SHIFT)) -#define STATIC_PAGE_MASK ((size_t)(STATIC_PAGE_SIZE - 1)) - -#ifdef PAGE_SHIFT -# undef PAGE_SHIFT -#endif -#ifdef PAGE_SIZE -# undef PAGE_SIZE -#endif +/* Page size. STATIC_PAGE_SHIFT is determined by the configure script. */ #ifdef PAGE_MASK # undef PAGE_MASK #endif - -#ifdef DYNAMIC_PAGE_SHIFT -# define PAGE_SHIFT lg_pagesize -# define PAGE_SIZE pagesize -# define PAGE_MASK pagesize_mask -#else -# define PAGE_SHIFT STATIC_PAGE_SHIFT -# define PAGE_SIZE STATIC_PAGE_SIZE -# define PAGE_MASK STATIC_PAGE_MASK -#endif +#define LG_PAGE STATIC_PAGE_SHIFT +#define PAGE ((size_t)(1U << STATIC_PAGE_SHIFT)) +#define PAGE_MASK ((size_t)(PAGE - 1)) /* Return the smallest pagesize multiple that is >= s. */ #define PAGE_CEILING(s) \ (((s) + PAGE_MASK) & ~PAGE_MASK) -#include "jemalloc/internal/jemprn.h" +/* Return the nearest aligned address at or below a. */ +#define ALIGNMENT_ADDR2BASE(a, alignment) \ + ((void *)((uintptr_t)(a) & (-(alignment)))) + +/* Return the offset between a and the nearest aligned address at or below a. */ +#define ALIGNMENT_ADDR2OFFSET(a, alignment) \ + ((size_t)((uintptr_t)(a) & (alignment - 1))) + +/* Return the smallest alignment multiple that is >= s. */ +#define ALIGNMENT_CEILING(s, alignment) \ + (((s) + (alignment - 1)) & (-(alignment))) + +/* Declare a variable length array */ +#if __STDC_VERSION__ < 199901L +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# ifdef JEMALLOC_HAS_ALLOCA_H +# include <alloca.h> +# else +# include <stdlib.h> +# endif +# endif +# define VARIABLE_ARRAY(type, name, count) \ + type *name = alloca(sizeof(type) * count) +#else +# define VARIABLE_ARRAY(type, name, count) type name[count] +#endif + +#ifdef JEMALLOC_VALGRIND +/* + * The JEMALLOC_VALGRIND_*() macros must be macros rather than functions + * so that when Valgrind reports errors, there are no extra stack frames + * in the backtraces. + * + * The size that is reported to valgrind must be consistent through a chain of + * malloc..realloc..realloc calls. Request size isn't recorded anywhere in + * jemalloc, so it is critical that all callers of these macros provide usize + * rather than request size. As a result, buffer overflow detection is + * technically weakened for the standard API, though it is generally accepted + * practice to consider any extra bytes reported by malloc_usable_size() as + * usable space. + */ +#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do { \ + if (config_valgrind && opt_valgrind && cond) \ + VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(ptr), zero); \ +} while (0) +#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \ + old_rzsize, zero) do { \ + if (config_valgrind && opt_valgrind) { \ + size_t rzsize = p2rz(ptr); \ + \ + if (ptr == old_ptr) { \ + VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \ + usize, rzsize); \ + if (zero && old_usize < usize) { \ + VALGRIND_MAKE_MEM_DEFINED( \ + (void *)((uintptr_t)ptr + \ + old_usize), usize - old_usize); \ + } \ + } else { \ + if (old_ptr != NULL) { \ + VALGRIND_FREELIKE_BLOCK(old_ptr, \ + old_rzsize); \ + } \ + if (ptr != NULL) { \ + size_t copy_size = (old_usize < usize) \ + ? old_usize : usize; \ + size_t tail_size = usize - copy_size; \ + VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, \ + rzsize, false); \ + if (copy_size > 0) { \ + VALGRIND_MAKE_MEM_DEFINED(ptr, \ + copy_size); \ + } \ + if (zero && tail_size > 0) { \ + VALGRIND_MAKE_MEM_DEFINED( \ + (void *)((uintptr_t)ptr + \ + copy_size), tail_size); \ + } \ + } \ + } \ + } \ +} while (0) +#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do { \ + if (config_valgrind && opt_valgrind) \ + VALGRIND_FREELIKE_BLOCK(ptr, rzsize); \ +} while (0) +#else +#define RUNNING_ON_VALGRIND ((unsigned)0) +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ + do {} while (0) +#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \ + do {} while (0) +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) do {} while (0) +#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len) do {} while (0) +#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len) do {} while (0) +#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len) do {} while (0) +#define JEMALLOC_VALGRIND_MALLOC(cond, ptr, usize, zero) do {} while (0) +#define JEMALLOC_VALGRIND_REALLOC(ptr, usize, old_ptr, old_usize, \ + old_rzsize, zero) do {} while (0) +#define JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0) +#endif + +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/prng.h" #include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/stats.h" #include "jemalloc/internal/ctl.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/tsd.h" #include "jemalloc/internal/mb.h" #include "jemalloc/internal/extent.h" #include "jemalloc/internal/arena.h" +#include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/base.h" #include "jemalloc/internal/chunk.h" #include "jemalloc/internal/huge.h" #include "jemalloc/internal/rtree.h" #include "jemalloc/internal/tcache.h" #include "jemalloc/internal/hash.h" -#ifdef JEMALLOC_ZONE -#include "jemalloc/internal/zone.h" -#endif +#include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" #undef JEMALLOC_H_TYPES /******************************************************************************/ #define JEMALLOC_H_STRUCTS -#include "jemalloc/internal/jemprn.h" +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/prng.h" #include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/stats.h" #include "jemalloc/internal/ctl.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/tsd.h" #include "jemalloc/internal/mb.h" +#include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/extent.h" #include "jemalloc/internal/arena.h" #include "jemalloc/internal/base.h" @@ -235,121 +499,68 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s); #include "jemalloc/internal/rtree.h" #include "jemalloc/internal/tcache.h" #include "jemalloc/internal/hash.h" -#ifdef JEMALLOC_ZONE -#include "jemalloc/internal/zone.h" -#endif +#include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" +typedef struct { + uint64_t allocated; + uint64_t deallocated; +} thread_allocated_t; +/* + * The JEMALLOC_CONCAT() wrapper is necessary to pass {0, 0} via a cpp macro + * argument. + */ +#define THREAD_ALLOCATED_INITIALIZER JEMALLOC_CONCAT({0, 0}) + #undef JEMALLOC_H_STRUCTS /******************************************************************************/ #define JEMALLOC_H_EXTERNS extern bool opt_abort; -#ifdef JEMALLOC_FILL extern bool opt_junk; -#endif -#ifdef JEMALLOC_SYSV -extern bool opt_sysv; -#endif -#ifdef JEMALLOC_XMALLOC +extern size_t opt_quarantine; +extern bool opt_redzone; +extern bool opt_utrace; +extern bool opt_valgrind; extern bool opt_xmalloc; -#endif -#ifdef JEMALLOC_FILL extern bool opt_zero; -#endif extern size_t opt_narenas; -#ifdef DYNAMIC_PAGE_SHIFT -extern size_t pagesize; -extern size_t pagesize_mask; -extern size_t lg_pagesize; -#endif - /* Number of CPUs. */ extern unsigned ncpus; -extern malloc_mutex_t arenas_lock; /* Protects arenas initialization. */ -#ifndef NO_TLS -/* - * Map of pthread_self() --> arenas[???], used for selecting an arena to use - * for allocations. - */ -extern __thread arena_t *arenas_tls JEMALLOC_ATTR(tls_model("initial-exec")); -# define ARENA_GET() arenas_tls -# define ARENA_SET(v) do { \ - arenas_tls = (v); \ -} while (0) -#else -extern pthread_key_t arenas_tsd; -# define ARENA_GET() ((arena_t *)pthread_getspecific(arenas_tsd)) -# define ARENA_SET(v) do { \ - pthread_setspecific(arenas_tsd, (void *)(v)); \ -} while (0) -#endif - +/* Protects arenas initialization (arenas, arenas_total). */ +extern malloc_mutex_t arenas_lock; /* * Arenas that are used to service external requests. Not all elements of the * arenas array are necessarily used; arenas are created lazily as needed. + * + * arenas[0..narenas_auto) are used for automatic multiplexing of threads and + * arenas. arenas[narenas_auto..narenas_total) are only used if the application + * takes some action to create them and allocate from them. */ extern arena_t **arenas; -extern unsigned narenas; - -#ifdef JEMALLOC_STATS -typedef struct { - uint64_t allocated; - uint64_t deallocated; -} thread_allocated_t; -# ifndef NO_TLS -extern __thread thread_allocated_t thread_allocated_tls; -# define ALLOCATED_GET() thread_allocated_tls.allocated -# define DEALLOCATED_GET() thread_allocated_tls.deallocated -# define ALLOCATED_ADD(a, d) do { \ - thread_allocated_tls.allocated += a; \ - thread_allocated_tls.deallocated += d; \ -} while (0) -# else -extern pthread_key_t thread_allocated_tsd; -# define ALLOCATED_GET() \ - (uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \ - ? ((thread_allocated_t *) \ - pthread_getspecific(thread_allocated_tsd))->allocated : 0) -# define DEALLOCATED_GET() \ - (uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \ - ? ((thread_allocated_t \ - *)pthread_getspecific(thread_allocated_tsd))->deallocated : \ - 0) -# define ALLOCATED_ADD(a, d) do { \ - thread_allocated_t *thread_allocated = (thread_allocated_t *) \ - pthread_getspecific(thread_allocated_tsd); \ - if (thread_allocated != NULL) { \ - thread_allocated->allocated += (a); \ - thread_allocated->deallocated += (d); \ - } else { \ - thread_allocated = (thread_allocated_t *) \ - imalloc(sizeof(thread_allocated_t)); \ - if (thread_allocated != NULL) { \ - pthread_setspecific(thread_allocated_tsd, \ - thread_allocated); \ - thread_allocated->allocated = (a); \ - thread_allocated->deallocated = (d); \ - } \ - } \ -} while (0) -# endif -#endif +extern unsigned narenas_total; +extern unsigned narenas_auto; /* Read-only after initialization. */ arena_t *arenas_extend(unsigned ind); +void arenas_cleanup(void *arg); arena_t *choose_arena_hard(void); -int buferror(int errnum, char *buf, size_t buflen); void jemalloc_prefork(void); -void jemalloc_postfork(void); +void jemalloc_postfork_parent(void); +void jemalloc_postfork_child(void); -#include "jemalloc/internal/jemprn.h" +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/prng.h" #include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/stats.h" #include "jemalloc/internal/ctl.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/tsd.h" #include "jemalloc/internal/mb.h" +#include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/extent.h" #include "jemalloc/internal/arena.h" #include "jemalloc/internal/base.h" @@ -358,20 +569,22 @@ void jemalloc_postfork(void); #include "jemalloc/internal/rtree.h" #include "jemalloc/internal/tcache.h" #include "jemalloc/internal/hash.h" -#ifdef JEMALLOC_ZONE -#include "jemalloc/internal/zone.h" -#endif +#include "jemalloc/internal/quarantine.h" #include "jemalloc/internal/prof.h" #undef JEMALLOC_H_EXTERNS /******************************************************************************/ #define JEMALLOC_H_INLINES -#include "jemalloc/internal/jemprn.h" +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/prng.h" #include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/size_classes.h" #include "jemalloc/internal/stats.h" #include "jemalloc/internal/ctl.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/tsd.h" #include "jemalloc/internal/mb.h" #include "jemalloc/internal/extent.h" #include "jemalloc/internal/base.h" @@ -379,56 +592,49 @@ void jemalloc_postfork(void); #include "jemalloc/internal/huge.h" #ifndef JEMALLOC_ENABLE_INLINE -size_t pow2_ceil(size_t x); +malloc_tsd_protos(JEMALLOC_ATTR(unused), arenas, arena_t *) + size_t s2u(size_t size); -size_t sa2u(size_t size, size_t alignment, size_t *run_size_p); -void malloc_write(const char *s); -arena_t *choose_arena(void); +size_t sa2u(size_t size, size_t alignment); +unsigned narenas_total_get(void); +arena_t *choose_arena(arena_t *arena); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_)) -/* Compute the smallest power of 2 that is >= x. */ -JEMALLOC_INLINE size_t -pow2_ceil(size_t x) -{ - - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; -#if (LG_SIZEOF_PTR == 3) - x |= x >> 32; -#endif - x++; - return (x); -} +/* + * Map of pthread_self() --> arenas[???], used for selecting an arena to use + * for allocations. + */ +malloc_tsd_externs(arenas, arena_t *) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL, + arenas_cleanup) /* * Compute usable size that would result from allocating an object with the * specified size. */ -JEMALLOC_INLINE size_t +JEMALLOC_ALWAYS_INLINE size_t s2u(size_t size) { - if (size <= small_maxclass) - return arenas[0]->bins[small_size2bin[size]].reg_size; + if (size <= SMALL_MAXCLASS) + return (arena_bin_info[SMALL_SIZE2BIN(size)].reg_size); if (size <= arena_maxclass) - return PAGE_CEILING(size); - return CHUNK_CEILING(size); + return (PAGE_CEILING(size)); + return (CHUNK_CEILING(size)); } /* * Compute usable size that would result from allocating an object with the * specified size and alignment. */ -JEMALLOC_INLINE size_t -sa2u(size_t size, size_t alignment, size_t *run_size_p) +JEMALLOC_ALWAYS_INLINE size_t +sa2u(size_t size, size_t alignment) { size_t usize; + assert(alignment != 0 && ((alignment - 1) & alignment) == 0); + /* * Round size up to the nearest multiple of alignment. * @@ -442,12 +648,8 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p) * 96 | 1100000 | 32 * 144 | 10100000 | 32 * 192 | 11000000 | 64 - * - * Depending on runtime settings, it is possible that arena_malloc() - * will further round up to a power of two, but that never causes - * correctness issues. */ - usize = (size + (alignment - 1)) & (-alignment); + usize = ALIGNMENT_CEILING(size, alignment); /* * (usize < size) protects against the combination of maximal * alignment and size greater than maximal alignment. @@ -457,11 +659,9 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p) return (0); } - if (usize <= arena_maxclass && alignment <= PAGE_SIZE) { - if (usize <= small_maxclass) { - return - (arenas[0]->bins[small_size2bin[usize]].reg_size); - } + if (usize <= arena_maxclass && alignment <= PAGE) { + if (usize <= SMALL_MAXCLASS) + return (arena_bin_info[SMALL_SIZE2BIN(usize)].reg_size); return (PAGE_CEILING(usize)); } else { size_t run_size; @@ -474,7 +674,7 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p) usize = PAGE_CEILING(size); /* * (usize < size) protects against very large sizes within - * PAGE_SIZE of SIZE_T_MAX. + * PAGE of SIZE_T_MAX. * * (usize + alignment < usize) protects against the * combination of maximal alignment and usize large enough @@ -492,52 +692,38 @@ sa2u(size_t size, size_t alignment, size_t *run_size_p) /* * Calculate the size of the over-size run that arena_palloc() * would need to allocate in order to guarantee the alignment. + * If the run wouldn't fit within a chunk, round up to a huge + * allocation size. */ - if (usize >= alignment) - run_size = usize + alignment - PAGE_SIZE; - else { - /* - * It is possible that (alignment << 1) will cause - * overflow, but it doesn't matter because we also - * subtract PAGE_SIZE, which in the case of overflow - * leaves us with a very large run_size. That causes - * the first conditional below to fail, which means - * that the bogus run_size value never gets used for - * anything important. - */ - run_size = (alignment << 1) - PAGE_SIZE; - } - if (run_size_p != NULL) - *run_size_p = run_size; - + run_size = usize + alignment - PAGE; if (run_size <= arena_maxclass) return (PAGE_CEILING(usize)); return (CHUNK_CEILING(usize)); } } -/* - * Wrapper around malloc_message() that avoids the need for - * JEMALLOC_P(malloc_message)(...) throughout the code. - */ -JEMALLOC_INLINE void -malloc_write(const char *s) +JEMALLOC_INLINE unsigned +narenas_total_get(void) { + unsigned narenas; + + malloc_mutex_lock(&arenas_lock); + narenas = narenas_total; + malloc_mutex_unlock(&arenas_lock); - JEMALLOC_P(malloc_message)(NULL, s); + return (narenas); } -/* - * Choose an arena based on a per-thread value (fast-path code, calls slow-path - * code if necessary). - */ +/* Choose an arena based on a per-thread value. */ JEMALLOC_INLINE arena_t * -choose_arena(void) +choose_arena(arena_t *arena) { arena_t *ret; - ret = ARENA_GET(); - if (ret == NULL) { + if (arena != NULL) + return (arena); + + if ((ret = *arenas_tsd_get()) == NULL) { ret = choose_arena_hard(); assert(ret != NULL); } @@ -546,117 +732,174 @@ choose_arena(void) } #endif +#include "jemalloc/internal/bitmap.h" #include "jemalloc/internal/rtree.h" +/* + * Include arena.h twice in order to resolve circular dependencies with + * tcache.h. + */ +#define JEMALLOC_ARENA_INLINE_A +#include "jemalloc/internal/arena.h" +#undef JEMALLOC_ARENA_INLINE_A #include "jemalloc/internal/tcache.h" +#define JEMALLOC_ARENA_INLINE_B #include "jemalloc/internal/arena.h" +#undef JEMALLOC_ARENA_INLINE_B #include "jemalloc/internal/hash.h" -#ifdef JEMALLOC_ZONE -#include "jemalloc/internal/zone.h" -#endif +#include "jemalloc/internal/quarantine.h" #ifndef JEMALLOC_ENABLE_INLINE +void *imallocx(size_t size, bool try_tcache, arena_t *arena); void *imalloc(size_t size); +void *icallocx(size_t size, bool try_tcache, arena_t *arena); void *icalloc(size_t size); -void *ipalloc(size_t size, size_t alignment, bool zero); -size_t isalloc(const void *ptr); -# ifdef JEMALLOC_IVSALLOC -size_t ivsalloc(const void *ptr); -# endif +void *ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena); +void *ipalloc(size_t usize, size_t alignment, bool zero); +size_t isalloc(const void *ptr, bool demote); +size_t ivsalloc(const void *ptr, bool demote); +size_t u2rz(size_t usize); +size_t p2rz(const void *ptr); +void idallocx(void *ptr, bool try_tcache); void idalloc(void *ptr); +void iqallocx(void *ptr, bool try_tcache); +void iqalloc(void *ptr); +void *irallocx(void *ptr, size_t size, size_t extra, size_t alignment, + bool zero, bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, + arena_t *arena); void *iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, bool no_move); +malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t) #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_)) -JEMALLOC_INLINE void * -imalloc(size_t size) +JEMALLOC_ALWAYS_INLINE void * +imallocx(size_t size, bool try_tcache, arena_t *arena) { assert(size != 0); if (size <= arena_maxclass) - return (arena_malloc(size, false)); + return (arena_malloc(arena, size, false, try_tcache)); else return (huge_malloc(size, false)); } -JEMALLOC_INLINE void * -icalloc(size_t size) +JEMALLOC_ALWAYS_INLINE void * +imalloc(size_t size) +{ + + return (imallocx(size, true, NULL)); +} + +JEMALLOC_ALWAYS_INLINE void * +icallocx(size_t size, bool try_tcache, arena_t *arena) { if (size <= arena_maxclass) - return (arena_malloc(size, true)); + return (arena_malloc(arena, size, true, try_tcache)); else return (huge_malloc(size, true)); } -JEMALLOC_INLINE void * -ipalloc(size_t size, size_t alignment, bool zero) +JEMALLOC_ALWAYS_INLINE void * +icalloc(size_t size) +{ + + return (icallocx(size, true, NULL)); +} + +JEMALLOC_ALWAYS_INLINE void * +ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena) { void *ret; - size_t usize; - size_t run_size -# ifdef JEMALLOC_CC_SILENCE - = 0 -# endif - ; - - usize = sa2u(size, alignment, &run_size); - if (usize == 0) - return (NULL); - if (usize <= arena_maxclass && alignment <= PAGE_SIZE) - ret = arena_malloc(usize, zero); - else if (run_size <= arena_maxclass) { - ret = arena_palloc(choose_arena(), usize, run_size, alignment, - zero); - } else if (alignment <= chunksize) - ret = huge_malloc(usize, zero); - else - ret = huge_palloc(usize, alignment, zero); - assert(((uintptr_t)ret & (alignment - 1)) == 0); + assert(usize != 0); + assert(usize == sa2u(usize, alignment)); + + if (usize <= arena_maxclass && alignment <= PAGE) + ret = arena_malloc(arena, usize, zero, try_tcache); + else { + if (usize <= arena_maxclass) { + ret = arena_palloc(choose_arena(arena), usize, + alignment, zero); + } else if (alignment <= chunksize) + ret = huge_malloc(usize, zero); + else + ret = huge_palloc(usize, alignment, zero); + } + + assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret); return (ret); } -JEMALLOC_INLINE size_t -isalloc(const void *ptr) +JEMALLOC_ALWAYS_INLINE void * +ipalloc(size_t usize, size_t alignment, bool zero) +{ + + return (ipallocx(usize, alignment, zero, true, NULL)); +} + +/* + * Typical usage: + * void *ptr = [...] + * size_t sz = isalloc(ptr, config_prof); + */ +JEMALLOC_ALWAYS_INLINE size_t +isalloc(const void *ptr, bool demote) { size_t ret; arena_chunk_t *chunk; assert(ptr != NULL); + /* Demotion only makes sense if config_prof is true. */ + assert(config_prof || demote == false); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk != ptr) { - /* Region. */ - assert(chunk->arena->magic == ARENA_MAGIC); - -#ifdef JEMALLOC_PROF - ret = arena_salloc_demote(ptr); -#else - ret = arena_salloc(ptr); -#endif - } else + if (chunk != ptr) + ret = arena_salloc(ptr, demote); + else ret = huge_salloc(ptr); return (ret); } -#ifdef JEMALLOC_IVSALLOC -JEMALLOC_INLINE size_t -ivsalloc(const void *ptr) +JEMALLOC_ALWAYS_INLINE size_t +ivsalloc(const void *ptr, bool demote) { /* Return 0 if ptr is not within a chunk managed by jemalloc. */ if (rtree_get(chunks_rtree, (uintptr_t)CHUNK_ADDR2BASE(ptr)) == NULL) return (0); - return (isalloc(ptr)); + return (isalloc(ptr, demote)); } -#endif -JEMALLOC_INLINE void -idalloc(void *ptr) +JEMALLOC_INLINE size_t +u2rz(size_t usize) +{ + size_t ret; + + if (usize <= SMALL_MAXCLASS) { + size_t binind = SMALL_SIZE2BIN(usize); + ret = arena_bin_info[binind].redzone_size; + } else + ret = 0; + + return (ret); +} + +JEMALLOC_INLINE size_t +p2rz(const void *ptr) +{ + size_t usize = isalloc(ptr, false); + + return (u2rz(usize)); +} + +JEMALLOC_ALWAYS_INLINE void +idallocx(void *ptr, bool try_tcache) { arena_chunk_t *chunk; @@ -664,14 +907,38 @@ idalloc(void *ptr) chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) - arena_dalloc(chunk->arena, chunk, ptr); + arena_dalloc(chunk->arena, chunk, ptr, try_tcache); else huge_dalloc(ptr, true); } -JEMALLOC_INLINE void * -iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, - bool no_move) +JEMALLOC_ALWAYS_INLINE void +idalloc(void *ptr) +{ + + idallocx(ptr, true); +} + +JEMALLOC_ALWAYS_INLINE void +iqallocx(void *ptr, bool try_tcache) +{ + + if (config_fill && opt_quarantine) + quarantine(ptr); + else + idallocx(ptr, try_tcache); +} + +JEMALLOC_ALWAYS_INLINE void +iqalloc(void *ptr) +{ + + iqallocx(ptr, true); +} + +JEMALLOC_ALWAYS_INLINE void * +irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, + bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena) { void *ret; size_t oldsize; @@ -679,24 +946,31 @@ iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, assert(ptr != NULL); assert(size != 0); - oldsize = isalloc(ptr); + oldsize = isalloc(ptr, config_prof); if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1)) != 0) { - size_t copysize; + size_t usize, copysize; /* - * Existing object alignment is inadquate; allocate new space + * Existing object alignment is inadequate; allocate new space * and copy. */ if (no_move) return (NULL); - ret = ipalloc(size + extra, alignment, zero); + usize = sa2u(size + extra, alignment); + if (usize == 0) + return (NULL); + ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena); if (ret == NULL) { if (extra == 0) return (NULL); /* Try again, without extra this time. */ - ret = ipalloc(size, alignment, zero); + usize = sa2u(size, alignment); + if (usize == 0) + return (NULL); + ret = ipallocx(usize, alignment, zero, try_tcache_alloc, + arena); if (ret == NULL) return (NULL); } @@ -707,7 +981,7 @@ iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, */ copysize = (size < oldsize) ? size : oldsize; memcpy(ret, ptr, copysize); - idalloc(ptr); + iqallocx(ptr, try_tcache_dalloc); return (ret); } @@ -721,17 +995,32 @@ iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, } } else { if (size + extra <= arena_maxclass) { - return (arena_ralloc(ptr, oldsize, size, extra, - alignment, zero)); + return (arena_ralloc(arena, ptr, oldsize, size, extra, + alignment, zero, try_tcache_alloc, + try_tcache_dalloc)); } else { return (huge_ralloc(ptr, oldsize, size, extra, - alignment, zero)); + alignment, zero, try_tcache_dalloc)); } } } + +JEMALLOC_ALWAYS_INLINE void * +iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero, + bool no_move) +{ + + return (irallocx(ptr, size, extra, alignment, zero, no_move, true, true, + NULL)); +} + +malloc_tsd_externs(thread_allocated, thread_allocated_t) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, thread_allocated, thread_allocated_t, + THREAD_ALLOCATED_INITIALIZER, malloc_tsd_no_cleanup) #endif #include "jemalloc/internal/prof.h" #undef JEMALLOC_H_INLINES /******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_H */ diff --git a/dep/jemalloc/include/jemalloc/internal/mb.h b/dep/jemalloc/include/jemalloc/internal/mb.h index 1707aa91d68..3cfa7872942 100644 --- a/dep/jemalloc/include/jemalloc/internal/mb.h +++ b/dep/jemalloc/include/jemalloc/internal/mb.h @@ -17,7 +17,7 @@ void mb_write(void); #endif -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(MB_C_)) +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_)) #ifdef __i386__ /* * According to the Intel Architecture Software Developer's Manual, current @@ -54,7 +54,7 @@ mb_write(void) ); #endif } -#elif (defined(__amd64_) || defined(__x86_64__)) +#elif (defined(__amd64__) || defined(__x86_64__)) JEMALLOC_INLINE void mb_write(void) { @@ -87,6 +87,13 @@ mb_write(void) : "memory" /* Clobbers. */ ); } +#elif defined(__tile__) +JEMALLOC_INLINE void +mb_write(void) +{ + + __sync_synchronize(); +} #else /* * This is much slower than a simple memory barrier, but the semantics of mutex diff --git a/dep/jemalloc/include/jemalloc/internal/mutex.h b/dep/jemalloc/include/jemalloc/internal/mutex.h index dcca01edd5d..de44e1435ad 100644 --- a/dep/jemalloc/include/jemalloc/internal/mutex.h +++ b/dep/jemalloc/include/jemalloc/internal/mutex.h @@ -1,18 +1,42 @@ /******************************************************************************/ #ifdef JEMALLOC_H_TYPES -typedef pthread_mutex_t malloc_mutex_t; +typedef struct malloc_mutex_s malloc_mutex_t; -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -# define MALLOC_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +#ifdef _WIN32 +# define MALLOC_MUTEX_INITIALIZER +#elif (defined(JEMALLOC_OSSPIN)) +# define MALLOC_MUTEX_INITIALIZER {0} +#elif (defined(JEMALLOC_MUTEX_INIT_CB)) +# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL} #else -# define MALLOC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +# if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \ + defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)) +# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP +# define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} +# else +# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT +# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER} +# endif #endif #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS +struct malloc_mutex_s { +#ifdef _WIN32 + CRITICAL_SECTION lock; +#elif (defined(JEMALLOC_OSSPIN)) + OSSpinLock lock; +#elif (defined(JEMALLOC_MUTEX_INIT_CB)) + pthread_mutex_t lock; + malloc_mutex_t *postponed_next; +#else + pthread_mutex_t lock; +#endif +}; + #endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ #ifdef JEMALLOC_H_EXTERNS @@ -20,11 +44,15 @@ typedef pthread_mutex_t malloc_mutex_t; #ifdef JEMALLOC_LAZY_LOCK extern bool isthreaded; #else +# undef isthreaded /* Undo private_namespace.h definition. */ # define isthreaded true #endif bool malloc_mutex_init(malloc_mutex_t *mutex); -void malloc_mutex_destroy(malloc_mutex_t *mutex); +void malloc_mutex_prefork(malloc_mutex_t *mutex); +void malloc_mutex_postfork_parent(malloc_mutex_t *mutex); +void malloc_mutex_postfork_child(malloc_mutex_t *mutex); +bool mutex_boot(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ @@ -32,7 +60,6 @@ void malloc_mutex_destroy(malloc_mutex_t *mutex); #ifndef JEMALLOC_ENABLE_INLINE void malloc_mutex_lock(malloc_mutex_t *mutex); -bool malloc_mutex_trylock(malloc_mutex_t *mutex); void malloc_mutex_unlock(malloc_mutex_t *mutex); #endif @@ -41,26 +68,30 @@ JEMALLOC_INLINE void malloc_mutex_lock(malloc_mutex_t *mutex) { - if (isthreaded) - pthread_mutex_lock(mutex); -} - -JEMALLOC_INLINE bool -malloc_mutex_trylock(malloc_mutex_t *mutex) -{ - - if (isthreaded) - return (pthread_mutex_trylock(mutex) != 0); - else - return (false); + if (isthreaded) { +#ifdef _WIN32 + EnterCriticalSection(&mutex->lock); +#elif (defined(JEMALLOC_OSSPIN)) + OSSpinLockLock(&mutex->lock); +#else + pthread_mutex_lock(&mutex->lock); +#endif + } } JEMALLOC_INLINE void malloc_mutex_unlock(malloc_mutex_t *mutex) { - if (isthreaded) - pthread_mutex_unlock(mutex); + if (isthreaded) { +#ifdef _WIN32 + LeaveCriticalSection(&mutex->lock); +#elif (defined(JEMALLOC_OSSPIN)) + OSSpinLockUnlock(&mutex->lock); +#else + pthread_mutex_unlock(&mutex->lock); +#endif + } } #endif diff --git a/dep/jemalloc/include/jemalloc/internal/private_namespace.h b/dep/jemalloc/include/jemalloc/internal/private_namespace.h new file mode 100644 index 00000000000..65de3163fd3 --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/private_namespace.h @@ -0,0 +1,390 @@ +#define a0calloc JEMALLOC_N(a0calloc) +#define a0free JEMALLOC_N(a0free) +#define a0malloc JEMALLOC_N(a0malloc) +#define arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small) +#define arena_bin_index JEMALLOC_N(arena_bin_index) +#define arena_bin_info JEMALLOC_N(arena_bin_info) +#define arena_boot JEMALLOC_N(arena_boot) +#define arena_dalloc JEMALLOC_N(arena_dalloc) +#define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin) +#define arena_dalloc_bin_locked JEMALLOC_N(arena_dalloc_bin_locked) +#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small) +#define arena_dalloc_large JEMALLOC_N(arena_dalloc_large) +#define arena_dalloc_large_locked JEMALLOC_N(arena_dalloc_large_locked) +#define arena_dalloc_small JEMALLOC_N(arena_dalloc_small) +#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get) +#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set) +#define arena_malloc JEMALLOC_N(arena_malloc) +#define arena_malloc_large JEMALLOC_N(arena_malloc_large) +#define arena_malloc_small JEMALLOC_N(arena_malloc_small) +#define arena_mapbits_allocated_get JEMALLOC_N(arena_mapbits_allocated_get) +#define arena_mapbits_binind_get JEMALLOC_N(arena_mapbits_binind_get) +#define arena_mapbits_dirty_get JEMALLOC_N(arena_mapbits_dirty_get) +#define arena_mapbits_get JEMALLOC_N(arena_mapbits_get) +#define arena_mapbits_large_binind_set JEMALLOC_N(arena_mapbits_large_binind_set) +#define arena_mapbits_large_get JEMALLOC_N(arena_mapbits_large_get) +#define arena_mapbits_large_set JEMALLOC_N(arena_mapbits_large_set) +#define arena_mapbits_large_size_get JEMALLOC_N(arena_mapbits_large_size_get) +#define arena_mapbits_small_runind_get JEMALLOC_N(arena_mapbits_small_runind_get) +#define arena_mapbits_small_set JEMALLOC_N(arena_mapbits_small_set) +#define arena_mapbits_unallocated_set JEMALLOC_N(arena_mapbits_unallocated_set) +#define arena_mapbits_unallocated_size_get JEMALLOC_N(arena_mapbits_unallocated_size_get) +#define arena_mapbits_unallocated_size_set JEMALLOC_N(arena_mapbits_unallocated_size_set) +#define arena_mapbits_unzeroed_get JEMALLOC_N(arena_mapbits_unzeroed_get) +#define arena_mapbits_unzeroed_set JEMALLOC_N(arena_mapbits_unzeroed_set) +#define arena_mapbitsp_get JEMALLOC_N(arena_mapbitsp_get) +#define arena_mapp_get JEMALLOC_N(arena_mapp_get) +#define arena_maxclass JEMALLOC_N(arena_maxclass) +#define arena_new JEMALLOC_N(arena_new) +#define arena_palloc JEMALLOC_N(arena_palloc) +#define arena_postfork_child JEMALLOC_N(arena_postfork_child) +#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent) +#define arena_prefork JEMALLOC_N(arena_prefork) +#define arena_prof_accum JEMALLOC_N(arena_prof_accum) +#define arena_prof_accum_impl JEMALLOC_N(arena_prof_accum_impl) +#define arena_prof_accum_locked JEMALLOC_N(arena_prof_accum_locked) +#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get) +#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set) +#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted) +#define arena_ptr_small_binind_get JEMALLOC_N(arena_ptr_small_binind_get) +#define arena_purge_all JEMALLOC_N(arena_purge_all) +#define arena_ralloc JEMALLOC_N(arena_ralloc) +#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move) +#define arena_run_regind JEMALLOC_N(arena_run_regind) +#define arena_salloc JEMALLOC_N(arena_salloc) +#define arena_stats_merge JEMALLOC_N(arena_stats_merge) +#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small) +#define arenas JEMALLOC_N(arenas) +#define arenas_booted JEMALLOC_N(arenas_booted) +#define arenas_cleanup JEMALLOC_N(arenas_cleanup) +#define arenas_extend JEMALLOC_N(arenas_extend) +#define arenas_initialized JEMALLOC_N(arenas_initialized) +#define arenas_lock JEMALLOC_N(arenas_lock) +#define arenas_tls JEMALLOC_N(arenas_tls) +#define arenas_tsd JEMALLOC_N(arenas_tsd) +#define arenas_tsd_boot JEMALLOC_N(arenas_tsd_boot) +#define arenas_tsd_cleanup_wrapper JEMALLOC_N(arenas_tsd_cleanup_wrapper) +#define arenas_tsd_get JEMALLOC_N(arenas_tsd_get) +#define arenas_tsd_get_wrapper JEMALLOC_N(arenas_tsd_get_wrapper) +#define arenas_tsd_set JEMALLOC_N(arenas_tsd_set) +#define atomic_add_u JEMALLOC_N(atomic_add_u) +#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32) +#define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64) +#define atomic_add_z JEMALLOC_N(atomic_add_z) +#define atomic_sub_u JEMALLOC_N(atomic_sub_u) +#define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32) +#define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64) +#define atomic_sub_z JEMALLOC_N(atomic_sub_z) +#define base_alloc JEMALLOC_N(base_alloc) +#define base_boot JEMALLOC_N(base_boot) +#define base_calloc JEMALLOC_N(base_calloc) +#define base_node_alloc JEMALLOC_N(base_node_alloc) +#define base_node_dealloc JEMALLOC_N(base_node_dealloc) +#define base_postfork_child JEMALLOC_N(base_postfork_child) +#define base_postfork_parent JEMALLOC_N(base_postfork_parent) +#define base_prefork JEMALLOC_N(base_prefork) +#define bitmap_full JEMALLOC_N(bitmap_full) +#define bitmap_get JEMALLOC_N(bitmap_get) +#define bitmap_info_init JEMALLOC_N(bitmap_info_init) +#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups) +#define bitmap_init JEMALLOC_N(bitmap_init) +#define bitmap_set JEMALLOC_N(bitmap_set) +#define bitmap_sfu JEMALLOC_N(bitmap_sfu) +#define bitmap_size JEMALLOC_N(bitmap_size) +#define bitmap_unset JEMALLOC_N(bitmap_unset) +#define bt_init JEMALLOC_N(bt_init) +#define buferror JEMALLOC_N(buferror) +#define choose_arena JEMALLOC_N(choose_arena) +#define choose_arena_hard JEMALLOC_N(choose_arena_hard) +#define chunk_alloc JEMALLOC_N(chunk_alloc) +#define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss) +#define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap) +#define chunk_boot JEMALLOC_N(chunk_boot) +#define chunk_dealloc JEMALLOC_N(chunk_dealloc) +#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap) +#define chunk_dss_boot JEMALLOC_N(chunk_dss_boot) +#define chunk_dss_postfork_child JEMALLOC_N(chunk_dss_postfork_child) +#define chunk_dss_postfork_parent JEMALLOC_N(chunk_dss_postfork_parent) +#define chunk_dss_prec_get JEMALLOC_N(chunk_dss_prec_get) +#define chunk_dss_prec_set JEMALLOC_N(chunk_dss_prec_set) +#define chunk_dss_prefork JEMALLOC_N(chunk_dss_prefork) +#define chunk_in_dss JEMALLOC_N(chunk_in_dss) +#define chunk_npages JEMALLOC_N(chunk_npages) +#define chunk_postfork_child JEMALLOC_N(chunk_postfork_child) +#define chunk_postfork_parent JEMALLOC_N(chunk_postfork_parent) +#define chunk_prefork JEMALLOC_N(chunk_prefork) +#define chunk_unmap JEMALLOC_N(chunk_unmap) +#define chunks_mtx JEMALLOC_N(chunks_mtx) +#define chunks_rtree JEMALLOC_N(chunks_rtree) +#define chunksize JEMALLOC_N(chunksize) +#define chunksize_mask JEMALLOC_N(chunksize_mask) +#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search) +#define ckh_count JEMALLOC_N(ckh_count) +#define ckh_delete JEMALLOC_N(ckh_delete) +#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert) +#define ckh_insert JEMALLOC_N(ckh_insert) +#define ckh_isearch JEMALLOC_N(ckh_isearch) +#define ckh_iter JEMALLOC_N(ckh_iter) +#define ckh_new JEMALLOC_N(ckh_new) +#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash) +#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp) +#define ckh_rebuild JEMALLOC_N(ckh_rebuild) +#define ckh_remove JEMALLOC_N(ckh_remove) +#define ckh_search JEMALLOC_N(ckh_search) +#define ckh_string_hash JEMALLOC_N(ckh_string_hash) +#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp) +#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert) +#define ckh_try_insert JEMALLOC_N(ckh_try_insert) +#define ctl_boot JEMALLOC_N(ctl_boot) +#define ctl_bymib JEMALLOC_N(ctl_bymib) +#define ctl_byname JEMALLOC_N(ctl_byname) +#define ctl_nametomib JEMALLOC_N(ctl_nametomib) +#define ctl_postfork_child JEMALLOC_N(ctl_postfork_child) +#define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent) +#define ctl_prefork JEMALLOC_N(ctl_prefork) +#define dss_prec_names JEMALLOC_N(dss_prec_names) +#define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first) +#define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert) +#define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter) +#define extent_tree_ad_iter_recurse JEMALLOC_N(extent_tree_ad_iter_recurse) +#define extent_tree_ad_iter_start JEMALLOC_N(extent_tree_ad_iter_start) +#define extent_tree_ad_last JEMALLOC_N(extent_tree_ad_last) +#define extent_tree_ad_new JEMALLOC_N(extent_tree_ad_new) +#define extent_tree_ad_next JEMALLOC_N(extent_tree_ad_next) +#define extent_tree_ad_nsearch JEMALLOC_N(extent_tree_ad_nsearch) +#define extent_tree_ad_prev JEMALLOC_N(extent_tree_ad_prev) +#define extent_tree_ad_psearch JEMALLOC_N(extent_tree_ad_psearch) +#define extent_tree_ad_remove JEMALLOC_N(extent_tree_ad_remove) +#define extent_tree_ad_reverse_iter JEMALLOC_N(extent_tree_ad_reverse_iter) +#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse) +#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start) +#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search) +#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first) +#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert) +#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter) +#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse) +#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start) +#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last) +#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new) +#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next) +#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch) +#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev) +#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch) +#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove) +#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter) +#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse) +#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start) +#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search) +#define get_errno JEMALLOC_N(get_errno) +#define hash JEMALLOC_N(hash) +#define hash_fmix_32 JEMALLOC_N(hash_fmix_32) +#define hash_fmix_64 JEMALLOC_N(hash_fmix_64) +#define hash_get_block_32 JEMALLOC_N(hash_get_block_32) +#define hash_get_block_64 JEMALLOC_N(hash_get_block_64) +#define hash_rotl_32 JEMALLOC_N(hash_rotl_32) +#define hash_rotl_64 JEMALLOC_N(hash_rotl_64) +#define hash_x64_128 JEMALLOC_N(hash_x64_128) +#define hash_x86_128 JEMALLOC_N(hash_x86_128) +#define hash_x86_32 JEMALLOC_N(hash_x86_32) +#define huge_allocated JEMALLOC_N(huge_allocated) +#define huge_boot JEMALLOC_N(huge_boot) +#define huge_dalloc JEMALLOC_N(huge_dalloc) +#define huge_malloc JEMALLOC_N(huge_malloc) +#define huge_mtx JEMALLOC_N(huge_mtx) +#define huge_ndalloc JEMALLOC_N(huge_ndalloc) +#define huge_nmalloc JEMALLOC_N(huge_nmalloc) +#define huge_palloc JEMALLOC_N(huge_palloc) +#define huge_postfork_child JEMALLOC_N(huge_postfork_child) +#define huge_postfork_parent JEMALLOC_N(huge_postfork_parent) +#define huge_prefork JEMALLOC_N(huge_prefork) +#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get) +#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set) +#define huge_ralloc JEMALLOC_N(huge_ralloc) +#define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move) +#define huge_salloc JEMALLOC_N(huge_salloc) +#define iallocm JEMALLOC_N(iallocm) +#define icalloc JEMALLOC_N(icalloc) +#define icallocx JEMALLOC_N(icallocx) +#define idalloc JEMALLOC_N(idalloc) +#define idallocx JEMALLOC_N(idallocx) +#define imalloc JEMALLOC_N(imalloc) +#define imallocx JEMALLOC_N(imallocx) +#define ipalloc JEMALLOC_N(ipalloc) +#define ipallocx JEMALLOC_N(ipallocx) +#define iqalloc JEMALLOC_N(iqalloc) +#define iqallocx JEMALLOC_N(iqallocx) +#define iralloc JEMALLOC_N(iralloc) +#define irallocx JEMALLOC_N(irallocx) +#define isalloc JEMALLOC_N(isalloc) +#define isthreaded JEMALLOC_N(isthreaded) +#define ivsalloc JEMALLOC_N(ivsalloc) +#define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child) +#define jemalloc_postfork_parent JEMALLOC_N(jemalloc_postfork_parent) +#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork) +#define malloc_cprintf JEMALLOC_N(malloc_cprintf) +#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init) +#define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock) +#define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child) +#define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent) +#define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork) +#define malloc_mutex_unlock JEMALLOC_N(malloc_mutex_unlock) +#define malloc_printf JEMALLOC_N(malloc_printf) +#define malloc_snprintf JEMALLOC_N(malloc_snprintf) +#define malloc_strtoumax JEMALLOC_N(malloc_strtoumax) +#define malloc_tsd_boot JEMALLOC_N(malloc_tsd_boot) +#define malloc_tsd_cleanup_register JEMALLOC_N(malloc_tsd_cleanup_register) +#define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc) +#define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc) +#define malloc_tsd_no_cleanup JEMALLOC_N(malloc_tsd_no_cleanup) +#define malloc_vcprintf JEMALLOC_N(malloc_vcprintf) +#define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf) +#define malloc_write JEMALLOC_N(malloc_write) +#define map_bias JEMALLOC_N(map_bias) +#define mb_write JEMALLOC_N(mb_write) +#define mutex_boot JEMALLOC_N(mutex_boot) +#define narenas_auto JEMALLOC_N(narenas_auto) +#define narenas_total JEMALLOC_N(narenas_total) +#define narenas_total_get JEMALLOC_N(narenas_total_get) +#define ncpus JEMALLOC_N(ncpus) +#define nhbins JEMALLOC_N(nhbins) +#define opt_abort JEMALLOC_N(opt_abort) +#define opt_junk JEMALLOC_N(opt_junk) +#define opt_lg_chunk JEMALLOC_N(opt_lg_chunk) +#define opt_lg_dirty_mult JEMALLOC_N(opt_lg_dirty_mult) +#define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval) +#define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample) +#define opt_lg_tcache_max JEMALLOC_N(opt_lg_tcache_max) +#define opt_narenas JEMALLOC_N(opt_narenas) +#define opt_prof JEMALLOC_N(opt_prof) +#define opt_prof_accum JEMALLOC_N(opt_prof_accum) +#define opt_prof_active JEMALLOC_N(opt_prof_active) +#define opt_prof_final JEMALLOC_N(opt_prof_final) +#define opt_prof_gdump JEMALLOC_N(opt_prof_gdump) +#define opt_prof_leak JEMALLOC_N(opt_prof_leak) +#define opt_prof_prefix JEMALLOC_N(opt_prof_prefix) +#define opt_quarantine JEMALLOC_N(opt_quarantine) +#define opt_redzone JEMALLOC_N(opt_redzone) +#define opt_stats_print JEMALLOC_N(opt_stats_print) +#define opt_tcache JEMALLOC_N(opt_tcache) +#define opt_utrace JEMALLOC_N(opt_utrace) +#define opt_valgrind JEMALLOC_N(opt_valgrind) +#define opt_xmalloc JEMALLOC_N(opt_xmalloc) +#define opt_zero JEMALLOC_N(opt_zero) +#define p2rz JEMALLOC_N(p2rz) +#define pages_purge JEMALLOC_N(pages_purge) +#define pow2_ceil JEMALLOC_N(pow2_ceil) +#define prof_backtrace JEMALLOC_N(prof_backtrace) +#define prof_boot0 JEMALLOC_N(prof_boot0) +#define prof_boot1 JEMALLOC_N(prof_boot1) +#define prof_boot2 JEMALLOC_N(prof_boot2) +#define prof_ctx_get JEMALLOC_N(prof_ctx_get) +#define prof_ctx_set JEMALLOC_N(prof_ctx_set) +#define prof_free JEMALLOC_N(prof_free) +#define prof_gdump JEMALLOC_N(prof_gdump) +#define prof_idump JEMALLOC_N(prof_idump) +#define prof_interval JEMALLOC_N(prof_interval) +#define prof_lookup JEMALLOC_N(prof_lookup) +#define prof_malloc JEMALLOC_N(prof_malloc) +#define prof_mdump JEMALLOC_N(prof_mdump) +#define prof_postfork_child JEMALLOC_N(prof_postfork_child) +#define prof_postfork_parent JEMALLOC_N(prof_postfork_parent) +#define prof_prefork JEMALLOC_N(prof_prefork) +#define prof_promote JEMALLOC_N(prof_promote) +#define prof_realloc JEMALLOC_N(prof_realloc) +#define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update) +#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update) +#define prof_tdata_booted JEMALLOC_N(prof_tdata_booted) +#define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup) +#define prof_tdata_get JEMALLOC_N(prof_tdata_get) +#define prof_tdata_init JEMALLOC_N(prof_tdata_init) +#define prof_tdata_initialized JEMALLOC_N(prof_tdata_initialized) +#define prof_tdata_tls JEMALLOC_N(prof_tdata_tls) +#define prof_tdata_tsd JEMALLOC_N(prof_tdata_tsd) +#define prof_tdata_tsd_boot JEMALLOC_N(prof_tdata_tsd_boot) +#define prof_tdata_tsd_cleanup_wrapper JEMALLOC_N(prof_tdata_tsd_cleanup_wrapper) +#define prof_tdata_tsd_get JEMALLOC_N(prof_tdata_tsd_get) +#define prof_tdata_tsd_get_wrapper JEMALLOC_N(prof_tdata_tsd_get_wrapper) +#define prof_tdata_tsd_set JEMALLOC_N(prof_tdata_tsd_set) +#define quarantine JEMALLOC_N(quarantine) +#define quarantine_alloc_hook JEMALLOC_N(quarantine_alloc_hook) +#define quarantine_boot JEMALLOC_N(quarantine_boot) +#define quarantine_booted JEMALLOC_N(quarantine_booted) +#define quarantine_cleanup JEMALLOC_N(quarantine_cleanup) +#define quarantine_init JEMALLOC_N(quarantine_init) +#define quarantine_tls JEMALLOC_N(quarantine_tls) +#define quarantine_tsd JEMALLOC_N(quarantine_tsd) +#define quarantine_tsd_boot JEMALLOC_N(quarantine_tsd_boot) +#define quarantine_tsd_cleanup_wrapper JEMALLOC_N(quarantine_tsd_cleanup_wrapper) +#define quarantine_tsd_get JEMALLOC_N(quarantine_tsd_get) +#define quarantine_tsd_get_wrapper JEMALLOC_N(quarantine_tsd_get_wrapper) +#define quarantine_tsd_set JEMALLOC_N(quarantine_tsd_set) +#define register_zone JEMALLOC_N(register_zone) +#define rtree_get JEMALLOC_N(rtree_get) +#define rtree_get_locked JEMALLOC_N(rtree_get_locked) +#define rtree_new JEMALLOC_N(rtree_new) +#define rtree_postfork_child JEMALLOC_N(rtree_postfork_child) +#define rtree_postfork_parent JEMALLOC_N(rtree_postfork_parent) +#define rtree_prefork JEMALLOC_N(rtree_prefork) +#define rtree_set JEMALLOC_N(rtree_set) +#define s2u JEMALLOC_N(s2u) +#define sa2u JEMALLOC_N(sa2u) +#define set_errno JEMALLOC_N(set_errno) +#define stats_cactive JEMALLOC_N(stats_cactive) +#define stats_cactive_add JEMALLOC_N(stats_cactive_add) +#define stats_cactive_get JEMALLOC_N(stats_cactive_get) +#define stats_cactive_sub JEMALLOC_N(stats_cactive_sub) +#define stats_chunks JEMALLOC_N(stats_chunks) +#define stats_print JEMALLOC_N(stats_print) +#define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy) +#define tcache_alloc_large JEMALLOC_N(tcache_alloc_large) +#define tcache_alloc_small JEMALLOC_N(tcache_alloc_small) +#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard) +#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate) +#define tcache_arena_dissociate JEMALLOC_N(tcache_arena_dissociate) +#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large) +#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small) +#define tcache_bin_info JEMALLOC_N(tcache_bin_info) +#define tcache_boot0 JEMALLOC_N(tcache_boot0) +#define tcache_boot1 JEMALLOC_N(tcache_boot1) +#define tcache_booted JEMALLOC_N(tcache_booted) +#define tcache_create JEMALLOC_N(tcache_create) +#define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large) +#define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small) +#define tcache_destroy JEMALLOC_N(tcache_destroy) +#define tcache_enabled_booted JEMALLOC_N(tcache_enabled_booted) +#define tcache_enabled_get JEMALLOC_N(tcache_enabled_get) +#define tcache_enabled_initialized JEMALLOC_N(tcache_enabled_initialized) +#define tcache_enabled_set JEMALLOC_N(tcache_enabled_set) +#define tcache_enabled_tls JEMALLOC_N(tcache_enabled_tls) +#define tcache_enabled_tsd JEMALLOC_N(tcache_enabled_tsd) +#define tcache_enabled_tsd_boot JEMALLOC_N(tcache_enabled_tsd_boot) +#define tcache_enabled_tsd_cleanup_wrapper JEMALLOC_N(tcache_enabled_tsd_cleanup_wrapper) +#define tcache_enabled_tsd_get JEMALLOC_N(tcache_enabled_tsd_get) +#define tcache_enabled_tsd_get_wrapper JEMALLOC_N(tcache_enabled_tsd_get_wrapper) +#define tcache_enabled_tsd_set JEMALLOC_N(tcache_enabled_tsd_set) +#define tcache_event JEMALLOC_N(tcache_event) +#define tcache_event_hard JEMALLOC_N(tcache_event_hard) +#define tcache_flush JEMALLOC_N(tcache_flush) +#define tcache_get JEMALLOC_N(tcache_get) +#define tcache_initialized JEMALLOC_N(tcache_initialized) +#define tcache_maxclass JEMALLOC_N(tcache_maxclass) +#define tcache_salloc JEMALLOC_N(tcache_salloc) +#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge) +#define tcache_thread_cleanup JEMALLOC_N(tcache_thread_cleanup) +#define tcache_tls JEMALLOC_N(tcache_tls) +#define tcache_tsd JEMALLOC_N(tcache_tsd) +#define tcache_tsd_boot JEMALLOC_N(tcache_tsd_boot) +#define tcache_tsd_cleanup_wrapper JEMALLOC_N(tcache_tsd_cleanup_wrapper) +#define tcache_tsd_get JEMALLOC_N(tcache_tsd_get) +#define tcache_tsd_get_wrapper JEMALLOC_N(tcache_tsd_get_wrapper) +#define tcache_tsd_set JEMALLOC_N(tcache_tsd_set) +#define thread_allocated_booted JEMALLOC_N(thread_allocated_booted) +#define thread_allocated_initialized JEMALLOC_N(thread_allocated_initialized) +#define thread_allocated_tls JEMALLOC_N(thread_allocated_tls) +#define thread_allocated_tsd JEMALLOC_N(thread_allocated_tsd) +#define thread_allocated_tsd_boot JEMALLOC_N(thread_allocated_tsd_boot) +#define thread_allocated_tsd_cleanup_wrapper JEMALLOC_N(thread_allocated_tsd_cleanup_wrapper) +#define thread_allocated_tsd_get JEMALLOC_N(thread_allocated_tsd_get) +#define thread_allocated_tsd_get_wrapper JEMALLOC_N(thread_allocated_tsd_get_wrapper) +#define thread_allocated_tsd_set JEMALLOC_N(thread_allocated_tsd_set) +#define u2rz JEMALLOC_N(u2rz) diff --git a/dep/jemalloc/include/jemalloc/internal/jemprn.h b/dep/jemalloc/include/jemalloc/internal/prng.h index 0709d708012..83a5462b4dd 100644 --- a/dep/jemalloc/include/jemalloc/internal/jemprn.h +++ b/dep/jemalloc/include/jemalloc/internal/prng.h @@ -4,7 +4,7 @@ /* * Simple linear congruential pseudo-random number generator: * - * prn(y) = (a*x + c) % m + * prng(y) = (a*x + c) % m * * where the following constants ensure maximal period: * @@ -25,7 +25,7 @@ * uint32_t state : Seed value. * const uint32_t a, c : See above discussion. */ -#define prn32(r, lg_range, state, a, c) do { \ +#define prng32(r, lg_range, state, a, c) do { \ assert(lg_range > 0); \ assert(lg_range <= 32); \ \ @@ -34,8 +34,8 @@ r >>= (32 - lg_range); \ } while (false) -/* Same as prn32(), but 64 bits of pseudo-randomness, using uint64_t. */ -#define prn64(r, lg_range, state, a, c) do { \ +/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */ +#define prng64(r, lg_range, state, a, c) do { \ assert(lg_range > 0); \ assert(lg_range <= 64); \ \ diff --git a/dep/jemalloc/include/jemalloc/internal/prof.h b/dep/jemalloc/include/jemalloc/internal/prof.h index 7864000b88b..119a5b1bcb7 100644 --- a/dep/jemalloc/include/jemalloc/internal/prof.h +++ b/dep/jemalloc/include/jemalloc/internal/prof.h @@ -1,4 +1,3 @@ -#ifdef JEMALLOC_PROF /******************************************************************************/ #ifdef JEMALLOC_H_TYPES @@ -10,28 +9,41 @@ typedef struct prof_tdata_s prof_tdata_t; /* Option defaults. */ #define PROF_PREFIX_DEFAULT "jeprof" -#define LG_PROF_BT_MAX_DEFAULT 7 -#define LG_PROF_SAMPLE_DEFAULT 0 +#define LG_PROF_SAMPLE_DEFAULT 19 #define LG_PROF_INTERVAL_DEFAULT -1 -#define LG_PROF_TCMAX_DEFAULT -1 /* - * Hard limit on stack backtrace depth. Note that the version of - * prof_backtrace() that is based on __builtin_return_address() necessarily has - * a hard-coded number of backtrace frame handlers. + * Hard limit on stack backtrace depth. The version of prof_backtrace() that + * is based on __builtin_return_address() necessarily has a hard-coded number + * of backtrace frame handlers, and should be kept in sync with this setting. */ -#if (defined(JEMALLOC_PROF_LIBGCC) || defined(JEMALLOC_PROF_LIBUNWIND)) -# define LG_PROF_BT_MAX ((ZU(1) << (LG_SIZEOF_PTR+3)) - 1) -#else -# define LG_PROF_BT_MAX 7 /* >= LG_PROF_BT_MAX_DEFAULT */ -#endif -#define PROF_BT_MAX (1U << LG_PROF_BT_MAX) +#define PROF_BT_MAX 128 + +/* Maximum number of backtraces to store in each per thread LRU cache. */ +#define PROF_TCMAX 1024 /* Initial hash table size. */ -#define PROF_CKH_MINITEMS 64 +#define PROF_CKH_MINITEMS 64 /* Size of memory buffer to use when writing dump files. */ -#define PROF_DUMP_BUF_SIZE 65536 +#define PROF_DUMP_BUFSIZE 65536 + +/* Size of stack-allocated buffer used by prof_printf(). */ +#define PROF_PRINTF_BUFSIZE 128 + +/* + * Number of mutexes shared among all ctx's. No space is allocated for these + * unless profiling is enabled, so it's okay to over-provision. + */ +#define PROF_NCTX_LOCKS 1024 + +/* + * prof_tdata pointers close to NULL are used to encode state information that + * is used for cleaning up during thread shutdown. + */ +#define PROF_TDATA_STATE_REINCARNATED ((prof_tdata_t *)(uintptr_t)1) +#define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2) +#define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ @@ -109,8 +121,18 @@ struct prof_ctx_s { /* Associated backtrace. */ prof_bt_t *bt; - /* Protects cnt_merged and cnts_ql. */ - malloc_mutex_t lock; + /* Protects nlimbo, cnt_merged, and cnts_ql. */ + malloc_mutex_t *lock; + + /* + * Number of threads that currently cause this ctx to be in a state of + * limbo due to one of: + * - Initializing per thread counters associated with this ctx. + * - Preparing to destroy this ctx. + * nlimbo must be 1 (single destroyer) in order to safely destroy the + * ctx. + */ + unsigned nlimbo; /* Temporary storage for summation during dump. */ prof_cnt_t cnt_summed; @@ -145,9 +167,14 @@ struct prof_tdata_s { void **vec; /* Sampling state. */ - uint64_t prn_state; + uint64_t prng_state; uint64_t threshold; uint64_t accum; + + /* State used to avoid dumping while operating on prof internals. */ + bool enq; + bool enq_idump; + bool enq_gdump; }; #endif /* JEMALLOC_H_STRUCTS */ @@ -162,13 +189,12 @@ extern bool opt_prof; * to notice state changes. */ extern bool opt_prof_active; -extern size_t opt_lg_prof_bt_max; /* Maximum backtrace depth. */ extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */ extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */ extern bool opt_prof_gdump; /* High-water memory dumping. */ +extern bool opt_prof_final; /* Final profile dumping. */ extern bool opt_prof_leak; /* Dump leak summary at exit. */ extern bool opt_prof_accum; /* Report cumulative bytes. */ -extern ssize_t opt_lg_prof_tcmax; /* lg(max per thread bactrace cache) */ extern char opt_prof_prefix[PATH_MAX + 1]; /* @@ -186,50 +212,82 @@ extern uint64_t prof_interval; */ extern bool prof_promote; -/* (1U << opt_lg_prof_bt_max). */ -extern unsigned prof_bt_max; - -/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */ -#ifndef NO_TLS -extern __thread prof_tdata_t *prof_tdata_tls - JEMALLOC_ATTR(tls_model("initial-exec")); -# define PROF_TCACHE_GET() prof_tdata_tls -# define PROF_TCACHE_SET(v) do { \ - prof_tdata_tls = (v); \ - pthread_setspecific(prof_tdata_tsd, (void *)(v)); \ -} while (0) -#else -# define PROF_TCACHE_GET() \ - ((prof_tdata_t *)pthread_getspecific(prof_tdata_tsd)) -# define PROF_TCACHE_SET(v) do { \ - pthread_setspecific(prof_tdata_tsd, (void *)(v)); \ -} while (0) -#endif -/* - * Same contents as b2cnt_tls, but initialized such that the TSD destructor is - * called when a thread exits, so that prof_tdata_tls contents can be merged, - * unlinked, and deallocated. - */ -extern pthread_key_t prof_tdata_tsd; - void bt_init(prof_bt_t *bt, void **vec); -void prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max); +void prof_backtrace(prof_bt_t *bt, unsigned nignore); prof_thr_cnt_t *prof_lookup(prof_bt_t *bt); void prof_idump(void); bool prof_mdump(const char *filename); void prof_gdump(void); prof_tdata_t *prof_tdata_init(void); +void prof_tdata_cleanup(void *arg); void prof_boot0(void); void prof_boot1(void); bool prof_boot2(void); +void prof_prefork(void); +void prof_postfork_parent(void); +void prof_postfork_child(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ #ifdef JEMALLOC_H_INLINES +#define PROF_ALLOC_PREP(nignore, size, ret) do { \ + prof_tdata_t *prof_tdata; \ + prof_bt_t bt; \ + \ + assert(size == s2u(size)); \ + \ + prof_tdata = prof_tdata_get(true); \ + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) { \ + if (prof_tdata != NULL) \ + ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ + else \ + ret = NULL; \ + break; \ + } \ + \ + if (opt_prof_active == false) { \ + /* Sampling is currently inactive, so avoid sampling. */\ + ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ + } else if (opt_lg_prof_sample == 0) { \ + /* Don't bother with sampling logic, since sampling */\ + /* interval is 1. */\ + bt_init(&bt, prof_tdata->vec); \ + prof_backtrace(&bt, nignore); \ + ret = prof_lookup(&bt); \ + } else { \ + if (prof_tdata->threshold == 0) { \ + /* Initialize. Seed the prng differently for */\ + /* each thread. */\ + prof_tdata->prng_state = \ + (uint64_t)(uintptr_t)&size; \ + prof_sample_threshold_update(prof_tdata); \ + } \ + \ + /* Determine whether to capture a backtrace based on */\ + /* whether size is enough for prof_accum to reach */\ + /* prof_tdata->threshold. However, delay updating */\ + /* these variables until prof_{m,re}alloc(), because */\ + /* we don't know for sure that the allocation will */\ + /* succeed. */\ + /* */\ + /* Use subtraction rather than addition to avoid */\ + /* potential integer overflow. */\ + if (size >= prof_tdata->threshold - \ + prof_tdata->accum) { \ + bt_init(&bt, prof_tdata->vec); \ + prof_backtrace(&bt, nignore); \ + ret = prof_lookup(&bt); \ + } else \ + ret = (prof_thr_cnt_t *)(uintptr_t)1U; \ + } \ +} while (0) + #ifndef JEMALLOC_ENABLE_INLINE +malloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *) + +prof_tdata_t *prof_tdata_get(bool create); void prof_sample_threshold_update(prof_tdata_t *prof_tdata); -prof_thr_cnt_t *prof_alloc_prep(size_t size); prof_ctx_t *prof_ctx_get(const void *ptr); void prof_ctx_set(const void *ptr, prof_ctx_t *ctx); bool prof_sample_accum_update(size_t size); @@ -240,102 +298,71 @@ void prof_free(const void *ptr, size_t size); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_)) +/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */ +malloc_tsd_externs(prof_tdata, prof_tdata_t *) +malloc_tsd_funcs(JEMALLOC_INLINE, prof_tdata, prof_tdata_t *, NULL, + prof_tdata_cleanup) + +JEMALLOC_INLINE prof_tdata_t * +prof_tdata_get(bool create) +{ + prof_tdata_t *prof_tdata; + + cassert(config_prof); + + prof_tdata = *prof_tdata_tsd_get(); + if (create && prof_tdata == NULL) + prof_tdata = prof_tdata_init(); + + return (prof_tdata); +} + JEMALLOC_INLINE void prof_sample_threshold_update(prof_tdata_t *prof_tdata) { uint64_t r; double u; + cassert(config_prof); + /* - * Compute prof_sample_threshold as a geometrically distributed random + * Compute sample threshold as a geometrically distributed random * variable with mean (2^opt_lg_prof_sample). + * + * __ __ + * | log(u) | 1 + * prof_tdata->threshold = | -------- |, where p = ------------------- + * | log(1-p) | opt_lg_prof_sample + * 2 + * + * For more information on the math, see: + * + * Non-Uniform Random Variate Generation + * Luc Devroye + * Springer-Verlag, New York, 1986 + * pp 500 + * (http://cg.scs.carleton.ca/~luc/rnbookindex.html) */ - prn64(r, 53, prof_tdata->prn_state, - (uint64_t)6364136223846793005LLU, (uint64_t)1442695040888963407LLU); + prng64(r, 53, prof_tdata->prng_state, + UINT64_C(6364136223846793005), UINT64_C(1442695040888963407)); u = (double)r * (1.0/9007199254740992.0L); prof_tdata->threshold = (uint64_t)(log(u) / log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample)))) + (uint64_t)1U; } -JEMALLOC_INLINE prof_thr_cnt_t * -prof_alloc_prep(size_t size) -{ -#ifdef JEMALLOC_ENABLE_INLINE - /* This function does not have its own stack frame, because it is inlined. */ -# define NIGNORE 1 -#else -# define NIGNORE 2 -#endif - prof_thr_cnt_t *ret; - prof_tdata_t *prof_tdata; - prof_bt_t bt; - - assert(size == s2u(size)); - - prof_tdata = PROF_TCACHE_GET(); - if (prof_tdata == NULL) { - prof_tdata = prof_tdata_init(); - if (prof_tdata == NULL) - return (NULL); - } - - if (opt_prof_active == false) { - /* Sampling is currently inactive, so avoid sampling. */ - ret = (prof_thr_cnt_t *)(uintptr_t)1U; - } else if (opt_lg_prof_sample == 0) { - /* - * Don't bother with sampling logic, since sampling interval is - * 1. - */ - bt_init(&bt, prof_tdata->vec); - prof_backtrace(&bt, NIGNORE, prof_bt_max); - ret = prof_lookup(&bt); - } else { - if (prof_tdata->threshold == 0) { - /* - * Initialize. Seed the prng differently for each - * thread. - */ - prof_tdata->prn_state = (uint64_t)(uintptr_t)&size; - prof_sample_threshold_update(prof_tdata); - } - - /* - * Determine whether to capture a backtrace based on whether - * size is enough for prof_accum to reach - * prof_tdata->threshold. However, delay updating these - * variables until prof_{m,re}alloc(), because we don't know - * for sure that the allocation will succeed. - * - * Use subtraction rather than addition to avoid potential - * integer overflow. - */ - if (size >= prof_tdata->threshold - prof_tdata->accum) { - bt_init(&bt, prof_tdata->vec); - prof_backtrace(&bt, NIGNORE, prof_bt_max); - ret = prof_lookup(&bt); - } else - ret = (prof_thr_cnt_t *)(uintptr_t)1U; - } - - return (ret); -#undef NIGNORE -} - JEMALLOC_INLINE prof_ctx_t * prof_ctx_get(const void *ptr) { prof_ctx_t *ret; arena_chunk_t *chunk; + cassert(config_prof); assert(ptr != NULL); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) { /* Region. */ - assert(chunk->arena->magic == ARENA_MAGIC); - ret = arena_prof_ctx_get(ptr); } else ret = huge_prof_ctx_get(ptr); @@ -348,13 +375,12 @@ prof_ctx_set(const void *ptr, prof_ctx_t *ctx) { arena_chunk_t *chunk; + cassert(config_prof); assert(ptr != NULL); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) { /* Region. */ - assert(chunk->arena->magic == ARENA_MAGIC); - arena_prof_ctx_set(ptr, ctx); } else huge_prof_ctx_set(ptr, ctx); @@ -365,16 +391,18 @@ prof_sample_accum_update(size_t size) { prof_tdata_t *prof_tdata; + cassert(config_prof); /* Sampling logic is unnecessary if the interval is 1. */ assert(opt_lg_prof_sample != 0); - prof_tdata = PROF_TCACHE_GET(); - assert(prof_tdata != NULL); + prof_tdata = prof_tdata_get(false); + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + return (true); /* Take care to avoid integer overflow. */ if (size >= prof_tdata->threshold - prof_tdata->accum) { prof_tdata->accum -= (prof_tdata->threshold - size); - /* Compute new prof_sample_threshold. */ + /* Compute new sample threshold. */ prof_sample_threshold_update(prof_tdata); while (prof_tdata->accum >= prof_tdata->threshold) { prof_tdata->accum -= prof_tdata->threshold; @@ -391,8 +419,9 @@ JEMALLOC_INLINE void prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt) { + cassert(config_prof); assert(ptr != NULL); - assert(size == isalloc(ptr)); + assert(size == isalloc(ptr, true)); if (opt_lg_prof_sample != 0) { if (prof_sample_accum_update(size)) { @@ -401,7 +430,7 @@ prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt) * always possible to tell in advance how large an * object's usable size will be, so there should never * be a difference between the size passed to - * prof_alloc_prep() and prof_malloc(). + * PROF_ALLOC_PREP() and prof_malloc(). */ assert((uintptr_t)cnt == (uintptr_t)1U); } @@ -437,15 +466,16 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt, { prof_thr_cnt_t *told_cnt; + cassert(config_prof); assert(ptr != NULL || (uintptr_t)cnt <= (uintptr_t)1U); if (ptr != NULL) { - assert(size == isalloc(ptr)); + assert(size == isalloc(ptr, true)); if (opt_lg_prof_sample != 0) { if (prof_sample_accum_update(size)) { /* * Don't sample. The size passed to - * prof_alloc_prep() was larger than what + * PROF_ALLOC_PREP() was larger than what * actually got allocated, so a backtrace was * captured for this allocation, even though * its actual size was insufficient to cross @@ -463,10 +493,10 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt, * It's too late to propagate OOM for this realloc(), * so operate directly on old_cnt->ctx->cnt_merged. */ - malloc_mutex_lock(&old_ctx->lock); + malloc_mutex_lock(old_ctx->lock); old_ctx->cnt_merged.curobjs--; old_ctx->cnt_merged.curbytes -= old_size; - malloc_mutex_unlock(&old_ctx->lock); + malloc_mutex_unlock(old_ctx->lock); told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U; } } else @@ -477,7 +507,7 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt, if ((uintptr_t)cnt > (uintptr_t)1U) { prof_ctx_set(ptr, cnt->ctx); cnt->epoch++; - } else + } else if (ptr != NULL) prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U); /*********/ mb_write(); @@ -510,9 +540,12 @@ prof_free(const void *ptr, size_t size) { prof_ctx_t *ctx = prof_ctx_get(ptr); + cassert(config_prof); + if ((uintptr_t)ctx > (uintptr_t)1) { - assert(size == isalloc(ptr)); - prof_thr_cnt_t *tcnt = prof_lookup(ctx->bt); + prof_thr_cnt_t *tcnt; + assert(size == isalloc(ptr, true)); + tcnt = prof_lookup(ctx->bt); if (tcnt != NULL) { tcnt->epoch++; @@ -533,10 +566,10 @@ prof_free(const void *ptr, size_t size) * OOM during free() cannot be propagated, so operate * directly on cnt->ctx->cnt_merged. */ - malloc_mutex_lock(&ctx->lock); + malloc_mutex_lock(ctx->lock); ctx->cnt_merged.curobjs--; ctx->cnt_merged.curbytes -= size; - malloc_mutex_unlock(&ctx->lock); + malloc_mutex_unlock(ctx->lock); } } } @@ -544,4 +577,3 @@ prof_free(const void *ptr, size_t size) #endif /* JEMALLOC_H_INLINES */ /******************************************************************************/ -#endif /* JEMALLOC_PROF */ diff --git a/dep/jemalloc/include/jemalloc/internal/quarantine.h b/dep/jemalloc/include/jemalloc/internal/quarantine.h new file mode 100644 index 00000000000..16f677f73da --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/quarantine.h @@ -0,0 +1,67 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +typedef struct quarantine_obj_s quarantine_obj_t; +typedef struct quarantine_s quarantine_t; + +/* Default per thread quarantine size if valgrind is enabled. */ +#define JEMALLOC_VALGRIND_QUARANTINE_DEFAULT (ZU(1) << 24) + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +struct quarantine_obj_s { + void *ptr; + size_t usize; +}; + +struct quarantine_s { + size_t curbytes; + size_t curobjs; + size_t first; +#define LG_MAXOBJS_INIT 10 + size_t lg_maxobjs; + quarantine_obj_t objs[1]; /* Dynamically sized ring buffer. */ +}; + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +quarantine_t *quarantine_init(size_t lg_maxobjs); +void quarantine(void *ptr); +void quarantine_cleanup(void *arg); +bool quarantine_boot(void); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#ifndef JEMALLOC_ENABLE_INLINE +malloc_tsd_protos(JEMALLOC_ATTR(unused), quarantine, quarantine_t *) + +void quarantine_alloc_hook(void); +#endif + +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_)) +malloc_tsd_externs(quarantine, quarantine_t *) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, quarantine, quarantine_t *, NULL, + quarantine_cleanup) + +JEMALLOC_ALWAYS_INLINE void +quarantine_alloc_hook(void) +{ + quarantine_t *quarantine; + + assert(config_fill && opt_quarantine); + + quarantine = *quarantine_tsd_get(); + if (quarantine == NULL) + quarantine_init(LG_MAXOBJS_INIT); +} +#endif + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ + diff --git a/dep/jemalloc/include/jemalloc/internal/rb.h b/dep/jemalloc/include/jemalloc/internal/rb.h index ee9b009d235..7b675f09051 100644 --- a/dep/jemalloc/include/jemalloc/internal/rb.h +++ b/dep/jemalloc/include/jemalloc/internal/rb.h @@ -223,88 +223,88 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * The following API is generated: * * static void - * ex_new(ex_t *extree); + * ex_new(ex_t *tree); * Description: Initialize a red-black tree structure. * Args: - * extree: Pointer to an uninitialized red-black tree object. + * tree: Pointer to an uninitialized red-black tree object. * * static ex_node_t * - * ex_first(ex_t *extree); + * ex_first(ex_t *tree); * static ex_node_t * - * ex_last(ex_t *extree); - * Description: Get the first/last node in extree. + * ex_last(ex_t *tree); + * Description: Get the first/last node in tree. * Args: - * extree: Pointer to an initialized red-black tree object. - * Ret: First/last node in extree, or NULL if extree is empty. + * tree: Pointer to an initialized red-black tree object. + * Ret: First/last node in tree, or NULL if tree is empty. * * static ex_node_t * - * ex_next(ex_t *extree, ex_node_t *node); + * ex_next(ex_t *tree, ex_node_t *node); * static ex_node_t * - * ex_prev(ex_t *extree, ex_node_t *node); + * ex_prev(ex_t *tree, ex_node_t *node); * Description: Get node's successor/predecessor. * Args: - * extree: Pointer to an initialized red-black tree object. - * node : A node in extree. - * Ret: node's successor/predecessor in extree, or NULL if node is + * tree: Pointer to an initialized red-black tree object. + * node: A node in tree. + * Ret: node's successor/predecessor in tree, or NULL if node is * last/first. * * static ex_node_t * - * ex_search(ex_t *extree, ex_node_t *key); + * ex_search(ex_t *tree, ex_node_t *key); * Description: Search for node that matches key. * Args: - * extree: Pointer to an initialized red-black tree object. - * key : Search key. - * Ret: Node in extree that matches key, or NULL if no match. + * tree: Pointer to an initialized red-black tree object. + * key : Search key. + * Ret: Node in tree that matches key, or NULL if no match. * * static ex_node_t * - * ex_nsearch(ex_t *extree, ex_node_t *key); + * ex_nsearch(ex_t *tree, ex_node_t *key); * static ex_node_t * - * ex_psearch(ex_t *extree, ex_node_t *key); + * ex_psearch(ex_t *tree, ex_node_t *key); * Description: Search for node that matches key. If no match is found, * return what would be key's successor/predecessor, were - * key in extree. + * key in tree. * Args: - * extree: Pointer to an initialized red-black tree object. - * key : Search key. - * Ret: Node in extree that matches key, or if no match, hypothetical - * node's successor/predecessor (NULL if no successor/predecessor). + * tree: Pointer to an initialized red-black tree object. + * key : Search key. + * Ret: Node in tree that matches key, or if no match, hypothetical node's + * successor/predecessor (NULL if no successor/predecessor). * * static void - * ex_insert(ex_t *extree, ex_node_t *node); - * Description: Insert node into extree. + * ex_insert(ex_t *tree, ex_node_t *node); + * Description: Insert node into tree. * Args: - * extree: Pointer to an initialized red-black tree object. - * node : Node to be inserted into extree. + * tree: Pointer to an initialized red-black tree object. + * node: Node to be inserted into tree. * * static void - * ex_remove(ex_t *extree, ex_node_t *node); - * Description: Remove node from extree. + * ex_remove(ex_t *tree, ex_node_t *node); + * Description: Remove node from tree. * Args: - * extree: Pointer to an initialized red-black tree object. - * node : Node in extree to be removed. + * tree: Pointer to an initialized red-black tree object. + * node: Node in tree to be removed. * * static ex_node_t * - * ex_iter(ex_t *extree, ex_node_t *start, ex_node_t *(*cb)(ex_t *, + * ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *, * ex_node_t *, void *), void *arg); * static ex_node_t * - * ex_reverse_iter(ex_t *extree, ex_node_t *start, ex_node *(*cb)(ex_t *, + * ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *, * ex_node_t *, void *), void *arg); - * Description: Iterate forward/backward over extree, starting at node. - * If extree is modified, iteration must be immediately + * Description: Iterate forward/backward over tree, starting at node. If + * tree is modified, iteration must be immediately * terminated by the callback function that causes the * modification. * Args: - * extree: Pointer to an initialized red-black tree object. - * start : Node at which to start iteration, or NULL to start at - * first/last node. - * cb : Callback function, which is called for each node during - * iteration. Under normal circumstances the callback function - * should return NULL, which causes iteration to continue. If a - * callback function returns non-NULL, iteration is immediately - * terminated and the non-NULL return value is returned by the - * iterator. This is useful for re-starting iteration after - * modifying extree. - * arg : Opaque pointer passed to cb(). + * tree : Pointer to an initialized red-black tree object. + * start: Node at which to start iteration, or NULL to start at + * first/last node. + * cb : Callback function, which is called for each node during + * iteration. Under normal circumstances the callback function + * should return NULL, which causes iteration to continue. If a + * callback function returns non-NULL, iteration is immediately + * terminated and the non-NULL return value is returned by the + * iterator. This is useful for re-starting iteration after + * modifying tree. + * arg : Opaque pointer passed to cb(). * Ret: NULL if iteration completed, or the non-NULL callback return value * that caused termination of the iteration. */ diff --git a/dep/jemalloc/include/jemalloc/internal/rtree.h b/dep/jemalloc/include/jemalloc/internal/rtree.h index 9d58ebac545..9bd98548cfe 100644 --- a/dep/jemalloc/include/jemalloc/internal/rtree.h +++ b/dep/jemalloc/include/jemalloc/internal/rtree.h @@ -36,6 +36,9 @@ struct rtree_s { #ifdef JEMALLOC_H_EXTERNS rtree_t *rtree_new(unsigned bits); +void rtree_prefork(rtree_t *rtree); +void rtree_postfork_parent(rtree_t *rtree); +void rtree_postfork_child(rtree_t *rtree); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ @@ -49,7 +52,7 @@ void *rtree_get(rtree_t *rtree, uintptr_t key); bool rtree_set(rtree_t *rtree, uintptr_t key, void *val); #endif -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(RTREE_C_)) +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_)) #define RTREE_GET_GENERATE(f) \ /* The least significant bits of the key are ignored. */ \ JEMALLOC_INLINE void * \ diff --git a/dep/jemalloc/include/jemalloc/internal/size_classes.h b/dep/jemalloc/include/jemalloc/internal/size_classes.h new file mode 100644 index 00000000000..821102e5c1c --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/size_classes.h @@ -0,0 +1,721 @@ +/* This file was automatically generated by size_classes.sh. */ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 12) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 8, 24) \ + SIZE_CLASS(3, 8, 32) \ + SIZE_CLASS(4, 8, 40) \ + SIZE_CLASS(5, 8, 48) \ + SIZE_CLASS(6, 8, 56) \ + SIZE_CLASS(7, 8, 64) \ + SIZE_CLASS(8, 16, 80) \ + SIZE_CLASS(9, 16, 96) \ + SIZE_CLASS(10, 16, 112) \ + SIZE_CLASS(11, 16, 128) \ + SIZE_CLASS(12, 32, 160) \ + SIZE_CLASS(13, 32, 192) \ + SIZE_CLASS(14, 32, 224) \ + SIZE_CLASS(15, 32, 256) \ + SIZE_CLASS(16, 64, 320) \ + SIZE_CLASS(17, 64, 384) \ + SIZE_CLASS(18, 64, 448) \ + SIZE_CLASS(19, 64, 512) \ + SIZE_CLASS(20, 128, 640) \ + SIZE_CLASS(21, 128, 768) \ + SIZE_CLASS(22, 128, 896) \ + SIZE_CLASS(23, 128, 1024) \ + SIZE_CLASS(24, 256, 1280) \ + SIZE_CLASS(25, 256, 1536) \ + SIZE_CLASS(26, 256, 1792) \ + SIZE_CLASS(27, 256, 2048) \ + SIZE_CLASS(28, 512, 2560) \ + SIZE_CLASS(29, 512, 3072) \ + SIZE_CLASS(30, 512, 3584) \ + +#define NBINS 31 +#define SMALL_MAXCLASS 3584 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 13) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 8, 24) \ + SIZE_CLASS(3, 8, 32) \ + SIZE_CLASS(4, 8, 40) \ + SIZE_CLASS(5, 8, 48) \ + SIZE_CLASS(6, 8, 56) \ + SIZE_CLASS(7, 8, 64) \ + SIZE_CLASS(8, 16, 80) \ + SIZE_CLASS(9, 16, 96) \ + SIZE_CLASS(10, 16, 112) \ + SIZE_CLASS(11, 16, 128) \ + SIZE_CLASS(12, 32, 160) \ + SIZE_CLASS(13, 32, 192) \ + SIZE_CLASS(14, 32, 224) \ + SIZE_CLASS(15, 32, 256) \ + SIZE_CLASS(16, 64, 320) \ + SIZE_CLASS(17, 64, 384) \ + SIZE_CLASS(18, 64, 448) \ + SIZE_CLASS(19, 64, 512) \ + SIZE_CLASS(20, 128, 640) \ + SIZE_CLASS(21, 128, 768) \ + SIZE_CLASS(22, 128, 896) \ + SIZE_CLASS(23, 128, 1024) \ + SIZE_CLASS(24, 256, 1280) \ + SIZE_CLASS(25, 256, 1536) \ + SIZE_CLASS(26, 256, 1792) \ + SIZE_CLASS(27, 256, 2048) \ + SIZE_CLASS(28, 512, 2560) \ + SIZE_CLASS(29, 512, 3072) \ + SIZE_CLASS(30, 512, 3584) \ + SIZE_CLASS(31, 512, 4096) \ + SIZE_CLASS(32, 1024, 5120) \ + SIZE_CLASS(33, 1024, 6144) \ + SIZE_CLASS(34, 1024, 7168) \ + +#define NBINS 35 +#define SMALL_MAXCLASS 7168 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 14) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 8, 24) \ + SIZE_CLASS(3, 8, 32) \ + SIZE_CLASS(4, 8, 40) \ + SIZE_CLASS(5, 8, 48) \ + SIZE_CLASS(6, 8, 56) \ + SIZE_CLASS(7, 8, 64) \ + SIZE_CLASS(8, 16, 80) \ + SIZE_CLASS(9, 16, 96) \ + SIZE_CLASS(10, 16, 112) \ + SIZE_CLASS(11, 16, 128) \ + SIZE_CLASS(12, 32, 160) \ + SIZE_CLASS(13, 32, 192) \ + SIZE_CLASS(14, 32, 224) \ + SIZE_CLASS(15, 32, 256) \ + SIZE_CLASS(16, 64, 320) \ + SIZE_CLASS(17, 64, 384) \ + SIZE_CLASS(18, 64, 448) \ + SIZE_CLASS(19, 64, 512) \ + SIZE_CLASS(20, 128, 640) \ + SIZE_CLASS(21, 128, 768) \ + SIZE_CLASS(22, 128, 896) \ + SIZE_CLASS(23, 128, 1024) \ + SIZE_CLASS(24, 256, 1280) \ + SIZE_CLASS(25, 256, 1536) \ + SIZE_CLASS(26, 256, 1792) \ + SIZE_CLASS(27, 256, 2048) \ + SIZE_CLASS(28, 512, 2560) \ + SIZE_CLASS(29, 512, 3072) \ + SIZE_CLASS(30, 512, 3584) \ + SIZE_CLASS(31, 512, 4096) \ + SIZE_CLASS(32, 1024, 5120) \ + SIZE_CLASS(33, 1024, 6144) \ + SIZE_CLASS(34, 1024, 7168) \ + SIZE_CLASS(35, 1024, 8192) \ + SIZE_CLASS(36, 2048, 10240) \ + SIZE_CLASS(37, 2048, 12288) \ + SIZE_CLASS(38, 2048, 14336) \ + +#define NBINS 39 +#define SMALL_MAXCLASS 14336 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 15) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 8, 24) \ + SIZE_CLASS(3, 8, 32) \ + SIZE_CLASS(4, 8, 40) \ + SIZE_CLASS(5, 8, 48) \ + SIZE_CLASS(6, 8, 56) \ + SIZE_CLASS(7, 8, 64) \ + SIZE_CLASS(8, 16, 80) \ + SIZE_CLASS(9, 16, 96) \ + SIZE_CLASS(10, 16, 112) \ + SIZE_CLASS(11, 16, 128) \ + SIZE_CLASS(12, 32, 160) \ + SIZE_CLASS(13, 32, 192) \ + SIZE_CLASS(14, 32, 224) \ + SIZE_CLASS(15, 32, 256) \ + SIZE_CLASS(16, 64, 320) \ + SIZE_CLASS(17, 64, 384) \ + SIZE_CLASS(18, 64, 448) \ + SIZE_CLASS(19, 64, 512) \ + SIZE_CLASS(20, 128, 640) \ + SIZE_CLASS(21, 128, 768) \ + SIZE_CLASS(22, 128, 896) \ + SIZE_CLASS(23, 128, 1024) \ + SIZE_CLASS(24, 256, 1280) \ + SIZE_CLASS(25, 256, 1536) \ + SIZE_CLASS(26, 256, 1792) \ + SIZE_CLASS(27, 256, 2048) \ + SIZE_CLASS(28, 512, 2560) \ + SIZE_CLASS(29, 512, 3072) \ + SIZE_CLASS(30, 512, 3584) \ + SIZE_CLASS(31, 512, 4096) \ + SIZE_CLASS(32, 1024, 5120) \ + SIZE_CLASS(33, 1024, 6144) \ + SIZE_CLASS(34, 1024, 7168) \ + SIZE_CLASS(35, 1024, 8192) \ + SIZE_CLASS(36, 2048, 10240) \ + SIZE_CLASS(37, 2048, 12288) \ + SIZE_CLASS(38, 2048, 14336) \ + SIZE_CLASS(39, 2048, 16384) \ + SIZE_CLASS(40, 4096, 20480) \ + SIZE_CLASS(41, 4096, 24576) \ + SIZE_CLASS(42, 4096, 28672) \ + +#define NBINS 43 +#define SMALL_MAXCLASS 28672 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 16) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 8, 24) \ + SIZE_CLASS(3, 8, 32) \ + SIZE_CLASS(4, 8, 40) \ + SIZE_CLASS(5, 8, 48) \ + SIZE_CLASS(6, 8, 56) \ + SIZE_CLASS(7, 8, 64) \ + SIZE_CLASS(8, 16, 80) \ + SIZE_CLASS(9, 16, 96) \ + SIZE_CLASS(10, 16, 112) \ + SIZE_CLASS(11, 16, 128) \ + SIZE_CLASS(12, 32, 160) \ + SIZE_CLASS(13, 32, 192) \ + SIZE_CLASS(14, 32, 224) \ + SIZE_CLASS(15, 32, 256) \ + SIZE_CLASS(16, 64, 320) \ + SIZE_CLASS(17, 64, 384) \ + SIZE_CLASS(18, 64, 448) \ + SIZE_CLASS(19, 64, 512) \ + SIZE_CLASS(20, 128, 640) \ + SIZE_CLASS(21, 128, 768) \ + SIZE_CLASS(22, 128, 896) \ + SIZE_CLASS(23, 128, 1024) \ + SIZE_CLASS(24, 256, 1280) \ + SIZE_CLASS(25, 256, 1536) \ + SIZE_CLASS(26, 256, 1792) \ + SIZE_CLASS(27, 256, 2048) \ + SIZE_CLASS(28, 512, 2560) \ + SIZE_CLASS(29, 512, 3072) \ + SIZE_CLASS(30, 512, 3584) \ + SIZE_CLASS(31, 512, 4096) \ + SIZE_CLASS(32, 1024, 5120) \ + SIZE_CLASS(33, 1024, 6144) \ + SIZE_CLASS(34, 1024, 7168) \ + SIZE_CLASS(35, 1024, 8192) \ + SIZE_CLASS(36, 2048, 10240) \ + SIZE_CLASS(37, 2048, 12288) \ + SIZE_CLASS(38, 2048, 14336) \ + SIZE_CLASS(39, 2048, 16384) \ + SIZE_CLASS(40, 4096, 20480) \ + SIZE_CLASS(41, 4096, 24576) \ + SIZE_CLASS(42, 4096, 28672) \ + SIZE_CLASS(43, 4096, 32768) \ + SIZE_CLASS(44, 8192, 40960) \ + SIZE_CLASS(45, 8192, 49152) \ + SIZE_CLASS(46, 8192, 57344) \ + +#define NBINS 47 +#define SMALL_MAXCLASS 57344 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 16, 32) \ + SIZE_CLASS(3, 16, 48) \ + SIZE_CLASS(4, 16, 64) \ + SIZE_CLASS(5, 16, 80) \ + SIZE_CLASS(6, 16, 96) \ + SIZE_CLASS(7, 16, 112) \ + SIZE_CLASS(8, 16, 128) \ + SIZE_CLASS(9, 32, 160) \ + SIZE_CLASS(10, 32, 192) \ + SIZE_CLASS(11, 32, 224) \ + SIZE_CLASS(12, 32, 256) \ + SIZE_CLASS(13, 64, 320) \ + SIZE_CLASS(14, 64, 384) \ + SIZE_CLASS(15, 64, 448) \ + SIZE_CLASS(16, 64, 512) \ + SIZE_CLASS(17, 128, 640) \ + SIZE_CLASS(18, 128, 768) \ + SIZE_CLASS(19, 128, 896) \ + SIZE_CLASS(20, 128, 1024) \ + SIZE_CLASS(21, 256, 1280) \ + SIZE_CLASS(22, 256, 1536) \ + SIZE_CLASS(23, 256, 1792) \ + SIZE_CLASS(24, 256, 2048) \ + SIZE_CLASS(25, 512, 2560) \ + SIZE_CLASS(26, 512, 3072) \ + SIZE_CLASS(27, 512, 3584) \ + +#define NBINS 28 +#define SMALL_MAXCLASS 3584 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 13) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 16, 32) \ + SIZE_CLASS(3, 16, 48) \ + SIZE_CLASS(4, 16, 64) \ + SIZE_CLASS(5, 16, 80) \ + SIZE_CLASS(6, 16, 96) \ + SIZE_CLASS(7, 16, 112) \ + SIZE_CLASS(8, 16, 128) \ + SIZE_CLASS(9, 32, 160) \ + SIZE_CLASS(10, 32, 192) \ + SIZE_CLASS(11, 32, 224) \ + SIZE_CLASS(12, 32, 256) \ + SIZE_CLASS(13, 64, 320) \ + SIZE_CLASS(14, 64, 384) \ + SIZE_CLASS(15, 64, 448) \ + SIZE_CLASS(16, 64, 512) \ + SIZE_CLASS(17, 128, 640) \ + SIZE_CLASS(18, 128, 768) \ + SIZE_CLASS(19, 128, 896) \ + SIZE_CLASS(20, 128, 1024) \ + SIZE_CLASS(21, 256, 1280) \ + SIZE_CLASS(22, 256, 1536) \ + SIZE_CLASS(23, 256, 1792) \ + SIZE_CLASS(24, 256, 2048) \ + SIZE_CLASS(25, 512, 2560) \ + SIZE_CLASS(26, 512, 3072) \ + SIZE_CLASS(27, 512, 3584) \ + SIZE_CLASS(28, 512, 4096) \ + SIZE_CLASS(29, 1024, 5120) \ + SIZE_CLASS(30, 1024, 6144) \ + SIZE_CLASS(31, 1024, 7168) \ + +#define NBINS 32 +#define SMALL_MAXCLASS 7168 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 14) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 16, 32) \ + SIZE_CLASS(3, 16, 48) \ + SIZE_CLASS(4, 16, 64) \ + SIZE_CLASS(5, 16, 80) \ + SIZE_CLASS(6, 16, 96) \ + SIZE_CLASS(7, 16, 112) \ + SIZE_CLASS(8, 16, 128) \ + SIZE_CLASS(9, 32, 160) \ + SIZE_CLASS(10, 32, 192) \ + SIZE_CLASS(11, 32, 224) \ + SIZE_CLASS(12, 32, 256) \ + SIZE_CLASS(13, 64, 320) \ + SIZE_CLASS(14, 64, 384) \ + SIZE_CLASS(15, 64, 448) \ + SIZE_CLASS(16, 64, 512) \ + SIZE_CLASS(17, 128, 640) \ + SIZE_CLASS(18, 128, 768) \ + SIZE_CLASS(19, 128, 896) \ + SIZE_CLASS(20, 128, 1024) \ + SIZE_CLASS(21, 256, 1280) \ + SIZE_CLASS(22, 256, 1536) \ + SIZE_CLASS(23, 256, 1792) \ + SIZE_CLASS(24, 256, 2048) \ + SIZE_CLASS(25, 512, 2560) \ + SIZE_CLASS(26, 512, 3072) \ + SIZE_CLASS(27, 512, 3584) \ + SIZE_CLASS(28, 512, 4096) \ + SIZE_CLASS(29, 1024, 5120) \ + SIZE_CLASS(30, 1024, 6144) \ + SIZE_CLASS(31, 1024, 7168) \ + SIZE_CLASS(32, 1024, 8192) \ + SIZE_CLASS(33, 2048, 10240) \ + SIZE_CLASS(34, 2048, 12288) \ + SIZE_CLASS(35, 2048, 14336) \ + +#define NBINS 36 +#define SMALL_MAXCLASS 14336 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 15) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 16, 32) \ + SIZE_CLASS(3, 16, 48) \ + SIZE_CLASS(4, 16, 64) \ + SIZE_CLASS(5, 16, 80) \ + SIZE_CLASS(6, 16, 96) \ + SIZE_CLASS(7, 16, 112) \ + SIZE_CLASS(8, 16, 128) \ + SIZE_CLASS(9, 32, 160) \ + SIZE_CLASS(10, 32, 192) \ + SIZE_CLASS(11, 32, 224) \ + SIZE_CLASS(12, 32, 256) \ + SIZE_CLASS(13, 64, 320) \ + SIZE_CLASS(14, 64, 384) \ + SIZE_CLASS(15, 64, 448) \ + SIZE_CLASS(16, 64, 512) \ + SIZE_CLASS(17, 128, 640) \ + SIZE_CLASS(18, 128, 768) \ + SIZE_CLASS(19, 128, 896) \ + SIZE_CLASS(20, 128, 1024) \ + SIZE_CLASS(21, 256, 1280) \ + SIZE_CLASS(22, 256, 1536) \ + SIZE_CLASS(23, 256, 1792) \ + SIZE_CLASS(24, 256, 2048) \ + SIZE_CLASS(25, 512, 2560) \ + SIZE_CLASS(26, 512, 3072) \ + SIZE_CLASS(27, 512, 3584) \ + SIZE_CLASS(28, 512, 4096) \ + SIZE_CLASS(29, 1024, 5120) \ + SIZE_CLASS(30, 1024, 6144) \ + SIZE_CLASS(31, 1024, 7168) \ + SIZE_CLASS(32, 1024, 8192) \ + SIZE_CLASS(33, 2048, 10240) \ + SIZE_CLASS(34, 2048, 12288) \ + SIZE_CLASS(35, 2048, 14336) \ + SIZE_CLASS(36, 2048, 16384) \ + SIZE_CLASS(37, 4096, 20480) \ + SIZE_CLASS(38, 4096, 24576) \ + SIZE_CLASS(39, 4096, 28672) \ + +#define NBINS 40 +#define SMALL_MAXCLASS 28672 +#endif + +#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 16) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 8, 8) \ + SIZE_CLASS(1, 8, 16) \ + SIZE_CLASS(2, 16, 32) \ + SIZE_CLASS(3, 16, 48) \ + SIZE_CLASS(4, 16, 64) \ + SIZE_CLASS(5, 16, 80) \ + SIZE_CLASS(6, 16, 96) \ + SIZE_CLASS(7, 16, 112) \ + SIZE_CLASS(8, 16, 128) \ + SIZE_CLASS(9, 32, 160) \ + SIZE_CLASS(10, 32, 192) \ + SIZE_CLASS(11, 32, 224) \ + SIZE_CLASS(12, 32, 256) \ + SIZE_CLASS(13, 64, 320) \ + SIZE_CLASS(14, 64, 384) \ + SIZE_CLASS(15, 64, 448) \ + SIZE_CLASS(16, 64, 512) \ + SIZE_CLASS(17, 128, 640) \ + SIZE_CLASS(18, 128, 768) \ + SIZE_CLASS(19, 128, 896) \ + SIZE_CLASS(20, 128, 1024) \ + SIZE_CLASS(21, 256, 1280) \ + SIZE_CLASS(22, 256, 1536) \ + SIZE_CLASS(23, 256, 1792) \ + SIZE_CLASS(24, 256, 2048) \ + SIZE_CLASS(25, 512, 2560) \ + SIZE_CLASS(26, 512, 3072) \ + SIZE_CLASS(27, 512, 3584) \ + SIZE_CLASS(28, 512, 4096) \ + SIZE_CLASS(29, 1024, 5120) \ + SIZE_CLASS(30, 1024, 6144) \ + SIZE_CLASS(31, 1024, 7168) \ + SIZE_CLASS(32, 1024, 8192) \ + SIZE_CLASS(33, 2048, 10240) \ + SIZE_CLASS(34, 2048, 12288) \ + SIZE_CLASS(35, 2048, 14336) \ + SIZE_CLASS(36, 2048, 16384) \ + SIZE_CLASS(37, 4096, 20480) \ + SIZE_CLASS(38, 4096, 24576) \ + SIZE_CLASS(39, 4096, 28672) \ + SIZE_CLASS(40, 4096, 32768) \ + SIZE_CLASS(41, 8192, 40960) \ + SIZE_CLASS(42, 8192, 49152) \ + SIZE_CLASS(43, 8192, 57344) \ + +#define NBINS 44 +#define SMALL_MAXCLASS 57344 +#endif + +#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 16, 16) \ + SIZE_CLASS(1, 16, 32) \ + SIZE_CLASS(2, 16, 48) \ + SIZE_CLASS(3, 16, 64) \ + SIZE_CLASS(4, 16, 80) \ + SIZE_CLASS(5, 16, 96) \ + SIZE_CLASS(6, 16, 112) \ + SIZE_CLASS(7, 16, 128) \ + SIZE_CLASS(8, 32, 160) \ + SIZE_CLASS(9, 32, 192) \ + SIZE_CLASS(10, 32, 224) \ + SIZE_CLASS(11, 32, 256) \ + SIZE_CLASS(12, 64, 320) \ + SIZE_CLASS(13, 64, 384) \ + SIZE_CLASS(14, 64, 448) \ + SIZE_CLASS(15, 64, 512) \ + SIZE_CLASS(16, 128, 640) \ + SIZE_CLASS(17, 128, 768) \ + SIZE_CLASS(18, 128, 896) \ + SIZE_CLASS(19, 128, 1024) \ + SIZE_CLASS(20, 256, 1280) \ + SIZE_CLASS(21, 256, 1536) \ + SIZE_CLASS(22, 256, 1792) \ + SIZE_CLASS(23, 256, 2048) \ + SIZE_CLASS(24, 512, 2560) \ + SIZE_CLASS(25, 512, 3072) \ + SIZE_CLASS(26, 512, 3584) \ + +#define NBINS 27 +#define SMALL_MAXCLASS 3584 +#endif + +#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 13) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 16, 16) \ + SIZE_CLASS(1, 16, 32) \ + SIZE_CLASS(2, 16, 48) \ + SIZE_CLASS(3, 16, 64) \ + SIZE_CLASS(4, 16, 80) \ + SIZE_CLASS(5, 16, 96) \ + SIZE_CLASS(6, 16, 112) \ + SIZE_CLASS(7, 16, 128) \ + SIZE_CLASS(8, 32, 160) \ + SIZE_CLASS(9, 32, 192) \ + SIZE_CLASS(10, 32, 224) \ + SIZE_CLASS(11, 32, 256) \ + SIZE_CLASS(12, 64, 320) \ + SIZE_CLASS(13, 64, 384) \ + SIZE_CLASS(14, 64, 448) \ + SIZE_CLASS(15, 64, 512) \ + SIZE_CLASS(16, 128, 640) \ + SIZE_CLASS(17, 128, 768) \ + SIZE_CLASS(18, 128, 896) \ + SIZE_CLASS(19, 128, 1024) \ + SIZE_CLASS(20, 256, 1280) \ + SIZE_CLASS(21, 256, 1536) \ + SIZE_CLASS(22, 256, 1792) \ + SIZE_CLASS(23, 256, 2048) \ + SIZE_CLASS(24, 512, 2560) \ + SIZE_CLASS(25, 512, 3072) \ + SIZE_CLASS(26, 512, 3584) \ + SIZE_CLASS(27, 512, 4096) \ + SIZE_CLASS(28, 1024, 5120) \ + SIZE_CLASS(29, 1024, 6144) \ + SIZE_CLASS(30, 1024, 7168) \ + +#define NBINS 31 +#define SMALL_MAXCLASS 7168 +#endif + +#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 14) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 16, 16) \ + SIZE_CLASS(1, 16, 32) \ + SIZE_CLASS(2, 16, 48) \ + SIZE_CLASS(3, 16, 64) \ + SIZE_CLASS(4, 16, 80) \ + SIZE_CLASS(5, 16, 96) \ + SIZE_CLASS(6, 16, 112) \ + SIZE_CLASS(7, 16, 128) \ + SIZE_CLASS(8, 32, 160) \ + SIZE_CLASS(9, 32, 192) \ + SIZE_CLASS(10, 32, 224) \ + SIZE_CLASS(11, 32, 256) \ + SIZE_CLASS(12, 64, 320) \ + SIZE_CLASS(13, 64, 384) \ + SIZE_CLASS(14, 64, 448) \ + SIZE_CLASS(15, 64, 512) \ + SIZE_CLASS(16, 128, 640) \ + SIZE_CLASS(17, 128, 768) \ + SIZE_CLASS(18, 128, 896) \ + SIZE_CLASS(19, 128, 1024) \ + SIZE_CLASS(20, 256, 1280) \ + SIZE_CLASS(21, 256, 1536) \ + SIZE_CLASS(22, 256, 1792) \ + SIZE_CLASS(23, 256, 2048) \ + SIZE_CLASS(24, 512, 2560) \ + SIZE_CLASS(25, 512, 3072) \ + SIZE_CLASS(26, 512, 3584) \ + SIZE_CLASS(27, 512, 4096) \ + SIZE_CLASS(28, 1024, 5120) \ + SIZE_CLASS(29, 1024, 6144) \ + SIZE_CLASS(30, 1024, 7168) \ + SIZE_CLASS(31, 1024, 8192) \ + SIZE_CLASS(32, 2048, 10240) \ + SIZE_CLASS(33, 2048, 12288) \ + SIZE_CLASS(34, 2048, 14336) \ + +#define NBINS 35 +#define SMALL_MAXCLASS 14336 +#endif + +#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 15) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 16, 16) \ + SIZE_CLASS(1, 16, 32) \ + SIZE_CLASS(2, 16, 48) \ + SIZE_CLASS(3, 16, 64) \ + SIZE_CLASS(4, 16, 80) \ + SIZE_CLASS(5, 16, 96) \ + SIZE_CLASS(6, 16, 112) \ + SIZE_CLASS(7, 16, 128) \ + SIZE_CLASS(8, 32, 160) \ + SIZE_CLASS(9, 32, 192) \ + SIZE_CLASS(10, 32, 224) \ + SIZE_CLASS(11, 32, 256) \ + SIZE_CLASS(12, 64, 320) \ + SIZE_CLASS(13, 64, 384) \ + SIZE_CLASS(14, 64, 448) \ + SIZE_CLASS(15, 64, 512) \ + SIZE_CLASS(16, 128, 640) \ + SIZE_CLASS(17, 128, 768) \ + SIZE_CLASS(18, 128, 896) \ + SIZE_CLASS(19, 128, 1024) \ + SIZE_CLASS(20, 256, 1280) \ + SIZE_CLASS(21, 256, 1536) \ + SIZE_CLASS(22, 256, 1792) \ + SIZE_CLASS(23, 256, 2048) \ + SIZE_CLASS(24, 512, 2560) \ + SIZE_CLASS(25, 512, 3072) \ + SIZE_CLASS(26, 512, 3584) \ + SIZE_CLASS(27, 512, 4096) \ + SIZE_CLASS(28, 1024, 5120) \ + SIZE_CLASS(29, 1024, 6144) \ + SIZE_CLASS(30, 1024, 7168) \ + SIZE_CLASS(31, 1024, 8192) \ + SIZE_CLASS(32, 2048, 10240) \ + SIZE_CLASS(33, 2048, 12288) \ + SIZE_CLASS(34, 2048, 14336) \ + SIZE_CLASS(35, 2048, 16384) \ + SIZE_CLASS(36, 4096, 20480) \ + SIZE_CLASS(37, 4096, 24576) \ + SIZE_CLASS(38, 4096, 28672) \ + +#define NBINS 39 +#define SMALL_MAXCLASS 28672 +#endif + +#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 16) +#define SIZE_CLASSES_DEFINED +/* SIZE_CLASS(bin, delta, sz) */ +#define SIZE_CLASSES \ + SIZE_CLASS(0, 16, 16) \ + SIZE_CLASS(1, 16, 32) \ + SIZE_CLASS(2, 16, 48) \ + SIZE_CLASS(3, 16, 64) \ + SIZE_CLASS(4, 16, 80) \ + SIZE_CLASS(5, 16, 96) \ + SIZE_CLASS(6, 16, 112) \ + SIZE_CLASS(7, 16, 128) \ + SIZE_CLASS(8, 32, 160) \ + SIZE_CLASS(9, 32, 192) \ + SIZE_CLASS(10, 32, 224) \ + SIZE_CLASS(11, 32, 256) \ + SIZE_CLASS(12, 64, 320) \ + SIZE_CLASS(13, 64, 384) \ + SIZE_CLASS(14, 64, 448) \ + SIZE_CLASS(15, 64, 512) \ + SIZE_CLASS(16, 128, 640) \ + SIZE_CLASS(17, 128, 768) \ + SIZE_CLASS(18, 128, 896) \ + SIZE_CLASS(19, 128, 1024) \ + SIZE_CLASS(20, 256, 1280) \ + SIZE_CLASS(21, 256, 1536) \ + SIZE_CLASS(22, 256, 1792) \ + SIZE_CLASS(23, 256, 2048) \ + SIZE_CLASS(24, 512, 2560) \ + SIZE_CLASS(25, 512, 3072) \ + SIZE_CLASS(26, 512, 3584) \ + SIZE_CLASS(27, 512, 4096) \ + SIZE_CLASS(28, 1024, 5120) \ + SIZE_CLASS(29, 1024, 6144) \ + SIZE_CLASS(30, 1024, 7168) \ + SIZE_CLASS(31, 1024, 8192) \ + SIZE_CLASS(32, 2048, 10240) \ + SIZE_CLASS(33, 2048, 12288) \ + SIZE_CLASS(34, 2048, 14336) \ + SIZE_CLASS(35, 2048, 16384) \ + SIZE_CLASS(36, 4096, 20480) \ + SIZE_CLASS(37, 4096, 24576) \ + SIZE_CLASS(38, 4096, 28672) \ + SIZE_CLASS(39, 4096, 32768) \ + SIZE_CLASS(40, 8192, 40960) \ + SIZE_CLASS(41, 8192, 49152) \ + SIZE_CLASS(42, 8192, 57344) \ + +#define NBINS 43 +#define SMALL_MAXCLASS 57344 +#endif + +#ifndef SIZE_CLASSES_DEFINED +# error "No size class definitions match configuration" +#endif +#undef SIZE_CLASSES_DEFINED +/* + * The small_size2bin lookup table uses uint8_t to encode each bin index, so we + * cannot support more than 256 small size classes. Further constrain NBINS to + * 255 to support prof_promote, since all small size classes, plus a "not + * small" size class must be stored in 8 bits of arena_chunk_map_t's bits + * field. + */ +#if (NBINS > 255) +# error "Too many small size classes" +#endif + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/stats.h b/dep/jemalloc/include/jemalloc/internal/stats.h index 3fc2080a34b..27f68e3681c 100644 --- a/dep/jemalloc/include/jemalloc/internal/stats.h +++ b/dep/jemalloc/include/jemalloc/internal/stats.h @@ -1,25 +1,16 @@ /******************************************************************************/ #ifdef JEMALLOC_H_TYPES -#define UMAX2S_BUFSIZE 65 - -#ifdef JEMALLOC_STATS typedef struct tcache_bin_stats_s tcache_bin_stats_t; typedef struct malloc_bin_stats_s malloc_bin_stats_t; typedef struct malloc_large_stats_s malloc_large_stats_t; typedef struct arena_stats_s arena_stats_t; -#endif -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) typedef struct chunk_stats_s chunk_stats_t; -#endif #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS -#ifdef JEMALLOC_STATS - -#ifdef JEMALLOC_TCACHE struct tcache_bin_stats_s { /* * Number of allocation requests that corresponded to the size of this @@ -27,7 +18,6 @@ struct tcache_bin_stats_s { */ uint64_t nrequests; }; -#endif struct malloc_bin_stats_s { /* @@ -52,13 +42,11 @@ struct malloc_bin_stats_s { */ uint64_t nrequests; -#ifdef JEMALLOC_TCACHE /* Number of tcache fills from this bin. */ uint64_t nfills; /* Number of tcache flushes to this bin. */ uint64_t nflushes; -#endif /* Total number of runs created for this bin's size class. */ uint64_t nruns; @@ -69,9 +57,6 @@ struct malloc_bin_stats_s { */ uint64_t reruns; - /* High-water mark for this bin. */ - size_t highruns; - /* Current number of runs in this bin. */ size_t curruns; }; @@ -93,9 +78,6 @@ struct malloc_large_stats_s { */ uint64_t nrequests; - /* High-water mark for this size class. */ - size_t highruns; - /* Current number of runs of this size class. */ size_t curruns; }; @@ -127,14 +109,10 @@ struct arena_stats_s { */ malloc_large_stats_t *lstats; }; -#endif /* JEMALLOC_STATS */ -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) struct chunk_stats_s { -# ifdef JEMALLOC_STATS /* Number of chunks that were allocated. */ uint64_t nchunks; -# endif /* High-water mark for number of chunks allocated. */ size_t highchunks; @@ -146,7 +124,6 @@ struct chunk_stats_s { */ size_t curchunks; }; -#endif /* JEMALLOC_STATS */ #endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ @@ -154,21 +131,43 @@ struct chunk_stats_s { extern bool opt_stats_print; -char *u2s(uint64_t x, unsigned base, char *s); -#ifdef JEMALLOC_STATS -void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque, - const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4)); -void malloc_printf(const char *format, ...) - JEMALLOC_ATTR(format(printf, 1, 2)); -#endif +extern size_t stats_cactive; + void stats_print(void (*write)(void *, const char *), void *cbopaque, const char *opts); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ -#ifdef JEMALLOC_STATS #ifdef JEMALLOC_H_INLINES +#ifndef JEMALLOC_ENABLE_INLINE +size_t stats_cactive_get(void); +void stats_cactive_add(size_t size); +void stats_cactive_sub(size_t size); +#endif + +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_)) +JEMALLOC_INLINE size_t +stats_cactive_get(void) +{ + + return (atomic_read_z(&stats_cactive)); +} + +JEMALLOC_INLINE void +stats_cactive_add(size_t size) +{ + + atomic_add_z(&stats_cactive, size); +} + +JEMALLOC_INLINE void +stats_cactive_sub(size_t size) +{ + + atomic_sub_z(&stats_cactive, size); +} +#endif + #endif /* JEMALLOC_H_INLINES */ -#endif /* JEMALLOC_STATS */ /******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/tcache.h b/dep/jemalloc/include/jemalloc/internal/tcache.h index 1ad91a9b1e0..ba36204ff21 100644 --- a/dep/jemalloc/include/jemalloc/internal/tcache.h +++ b/dep/jemalloc/include/jemalloc/internal/tcache.h @@ -1,11 +1,21 @@ -#ifdef JEMALLOC_TCACHE /******************************************************************************/ #ifdef JEMALLOC_H_TYPES +typedef struct tcache_bin_info_s tcache_bin_info_t; typedef struct tcache_bin_s tcache_bin_t; typedef struct tcache_s tcache_t; /* + * tcache pointers close to NULL are used to encode state information that is + * used for two purposes: preventing thread caching on a per thread basis and + * cleaning up during thread shutdown. + */ +#define TCACHE_STATE_DISABLED ((tcache_t *)(uintptr_t)1) +#define TCACHE_STATE_REINCARNATED ((tcache_t *)(uintptr_t)2) +#define TCACHE_STATE_PURGATORY ((tcache_t *)(uintptr_t)3) +#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY + +/* * Absolute maximum number of cache slots for each small bin in the thread * cache. This is an additional constraint beyond that imposed as: twice the * number of regions per run for this size class. @@ -21,39 +31,55 @@ typedef struct tcache_s tcache_t; #define LG_TCACHE_MAXCLASS_DEFAULT 15 /* - * (1U << opt_lg_tcache_gc_sweep) is the approximate number of allocation - * events between full GC sweeps (-1: disabled). Integer rounding may cause - * the actual number to be slightly higher, since GC is performed - * incrementally. + * TCACHE_GC_SWEEP is the approximate number of allocation events between + * full GC sweeps. Integer rounding may cause the actual number to be + * slightly higher, since GC is performed incrementally. */ -#define LG_TCACHE_GC_SWEEP_DEFAULT 13 +#define TCACHE_GC_SWEEP 8192 + +/* Number of tcache allocation/deallocation events between incremental GCs. */ +#define TCACHE_GC_INCR \ + ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1)) #endif /* JEMALLOC_H_TYPES */ /******************************************************************************/ #ifdef JEMALLOC_H_STRUCTS +typedef enum { + tcache_enabled_false = 0, /* Enable cast to/from bool. */ + tcache_enabled_true = 1, + tcache_enabled_default = 2 +} tcache_enabled_t; + +/* + * Read-only information associated with each element of tcache_t's tbins array + * is stored separately, mainly to reduce memory usage. + */ +struct tcache_bin_info_s { + unsigned ncached_max; /* Upper limit on ncached. */ +}; + struct tcache_bin_s { -# ifdef JEMALLOC_STATS tcache_bin_stats_t tstats; -# endif - unsigned low_water; /* Min # cached since last GC. */ - unsigned high_water; /* Max # cached since last GC. */ + int low_water; /* Min # cached since last GC. */ + unsigned lg_fill_div; /* Fill (ncached_max >> lg_fill_div). */ unsigned ncached; /* # of cached objects. */ - unsigned ncached_max; /* Upper limit on ncached. */ - void *avail; /* Chain of available objects. */ + void **avail; /* Stack of available objects. */ }; struct tcache_s { -# ifdef JEMALLOC_STATS ql_elm(tcache_t) link; /* Used for aggregating stats. */ -# endif -# ifdef JEMALLOC_PROF uint64_t prof_accumbytes;/* Cleared after arena_prof_accum() */ -# endif arena_t *arena; /* This thread's arena. */ unsigned ev_cnt; /* Event count since incremental GC. */ unsigned next_gc_bin; /* Next bin to GC. */ tcache_bin_t tbins[1]; /* Dynamically sized. */ + /* + * The pointer stacks associated with tbins follow as a contiguous + * array. During tcache initialization, the avail pointer in each + * element of tbins is initialized to point to the proper offset within + * this array. + */ }; #endif /* JEMALLOC_H_STRUCTS */ @@ -62,27 +88,11 @@ struct tcache_s { extern bool opt_tcache; extern ssize_t opt_lg_tcache_max; -extern ssize_t opt_lg_tcache_gc_sweep; -/* Map of thread-specific caches. */ -#ifndef NO_TLS -extern __thread tcache_t *tcache_tls - JEMALLOC_ATTR(tls_model("initial-exec")); -# define TCACHE_GET() tcache_tls -# define TCACHE_SET(v) do { \ - tcache_tls = (tcache_t *)(v); \ - pthread_setspecific(tcache_tsd, (void *)(v)); \ -} while (0) -#else -# define TCACHE_GET() ((tcache_t *)pthread_getspecific(tcache_tsd)) -# define TCACHE_SET(v) do { \ - pthread_setspecific(tcache_tsd, (void *)(v)); \ -} while (0) -#endif -extern pthread_key_t tcache_tsd; +extern tcache_bin_info_t *tcache_bin_info; /* - * Number of tcache bins. There are nbins small-object bins, plus 0 or more + * Number of tcache bins. There are NBINS small-object bins, plus 0 or more * large-object bins. */ extern size_t nhbins; @@ -90,143 +100,202 @@ extern size_t nhbins; /* Maximum cached size class. */ extern size_t tcache_maxclass; -/* Number of tcache allocation/deallocation events between incremental GCs. */ -extern unsigned tcache_gc_incr; - -void tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache_t *tcache -#endif - ); -void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache_t *tcache -#endif - ); -tcache_t *tcache_create(arena_t *arena); +size_t tcache_salloc(const void *ptr); +void tcache_event_hard(tcache_t *tcache); void *tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind); +void tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem, + tcache_t *tcache); +void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem, + tcache_t *tcache); +void tcache_arena_associate(tcache_t *tcache, arena_t *arena); +void tcache_arena_dissociate(tcache_t *tcache); +tcache_t *tcache_create(arena_t *arena); void tcache_destroy(tcache_t *tcache); -#ifdef JEMALLOC_STATS +void tcache_thread_cleanup(void *arg); void tcache_stats_merge(tcache_t *tcache, arena_t *arena); -#endif -void tcache_boot(void); +bool tcache_boot0(void); +bool tcache_boot1(void); #endif /* JEMALLOC_H_EXTERNS */ /******************************************************************************/ #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE +malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tcache_t *) +malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache_enabled, tcache_enabled_t) + void tcache_event(tcache_t *tcache); -tcache_t *tcache_get(void); +void tcache_flush(void); +bool tcache_enabled_get(void); +tcache_t *tcache_get(bool create); +void tcache_enabled_set(bool enabled); void *tcache_alloc_easy(tcache_bin_t *tbin); void *tcache_alloc_small(tcache_t *tcache, size_t size, bool zero); void *tcache_alloc_large(tcache_t *tcache, size_t size, bool zero); -void tcache_dalloc_small(tcache_t *tcache, void *ptr); +void tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind); void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size); #endif #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_)) -JEMALLOC_INLINE tcache_t * -tcache_get(void) +/* Map of thread-specific caches. */ +malloc_tsd_externs(tcache, tcache_t *) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL, + tcache_thread_cleanup) +/* Per thread flag that allows thread caches to be disabled. */ +malloc_tsd_externs(tcache_enabled, tcache_enabled_t) +malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t, + tcache_enabled_default, malloc_tsd_no_cleanup) + +JEMALLOC_INLINE void +tcache_flush(void) +{ + tcache_t *tcache; + + cassert(config_tcache); + + tcache = *tcache_tsd_get(); + if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) + return; + tcache_destroy(tcache); + tcache = NULL; + tcache_tsd_set(&tcache); +} + +JEMALLOC_INLINE bool +tcache_enabled_get(void) +{ + tcache_enabled_t tcache_enabled; + + cassert(config_tcache); + + tcache_enabled = *tcache_enabled_tsd_get(); + if (tcache_enabled == tcache_enabled_default) { + tcache_enabled = (tcache_enabled_t)opt_tcache; + tcache_enabled_tsd_set(&tcache_enabled); + } + + return ((bool)tcache_enabled); +} + +JEMALLOC_INLINE void +tcache_enabled_set(bool enabled) { + tcache_enabled_t tcache_enabled; tcache_t *tcache; - if ((isthreaded & opt_tcache) == false) + cassert(config_tcache); + + tcache_enabled = (tcache_enabled_t)enabled; + tcache_enabled_tsd_set(&tcache_enabled); + tcache = *tcache_tsd_get(); + if (enabled) { + if (tcache == TCACHE_STATE_DISABLED) { + tcache = NULL; + tcache_tsd_set(&tcache); + } + } else /* disabled */ { + if (tcache > TCACHE_STATE_MAX) { + tcache_destroy(tcache); + tcache = NULL; + } + if (tcache == NULL) { + tcache = TCACHE_STATE_DISABLED; + tcache_tsd_set(&tcache); + } + } +} + +JEMALLOC_ALWAYS_INLINE tcache_t * +tcache_get(bool create) +{ + tcache_t *tcache; + + if (config_tcache == false) + return (NULL); + if (config_lazy_lock && isthreaded == false) return (NULL); - tcache = TCACHE_GET(); - if ((uintptr_t)tcache <= (uintptr_t)2) { + tcache = *tcache_tsd_get(); + if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) { + if (tcache == TCACHE_STATE_DISABLED) + return (NULL); if (tcache == NULL) { - tcache = tcache_create(choose_arena()); - if (tcache == NULL) - return (NULL); - } else { - if (tcache == (void *)(uintptr_t)1) { + if (create == false) { /* - * Make a note that an allocator function was - * called after the tcache_thread_cleanup() was - * called. + * Creating a tcache here would cause + * allocation as a side effect of free(). + * Ordinarily that would be okay since + * tcache_create() failure is a soft failure + * that doesn't propagate. However, if TLS + * data are freed via free() as in glibc, + * subtle corruption could result from setting + * a TLS variable after its backing memory is + * freed. */ - TCACHE_SET((uintptr_t)2); + return (NULL); } + if (tcache_enabled_get() == false) { + tcache_enabled_set(false); /* Memoize. */ + return (NULL); + } + return (tcache_create(choose_arena(NULL))); + } + if (tcache == TCACHE_STATE_PURGATORY) { + /* + * Make a note that an allocator function was called + * after tcache_thread_cleanup() was called. + */ + tcache = TCACHE_STATE_REINCARNATED; + tcache_tsd_set(&tcache); return (NULL); } + if (tcache == TCACHE_STATE_REINCARNATED) + return (NULL); + not_reached(); } return (tcache); } -JEMALLOC_INLINE void +JEMALLOC_ALWAYS_INLINE void tcache_event(tcache_t *tcache) { - if (tcache_gc_incr == 0) + if (TCACHE_GC_INCR == 0) return; tcache->ev_cnt++; - assert(tcache->ev_cnt <= tcache_gc_incr); - if (tcache->ev_cnt == tcache_gc_incr) { - size_t binind = tcache->next_gc_bin; - tcache_bin_t *tbin = &tcache->tbins[binind]; - - if (tbin->low_water > 0) { - /* - * Flush (ceiling) 3/4 of the objects below the low - * water mark. - */ - if (binind < nbins) { - tcache_bin_flush_small(tbin, binind, - tbin->ncached - tbin->low_water + - (tbin->low_water >> 2) -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); - } else { - tcache_bin_flush_large(tbin, binind, - tbin->ncached - tbin->low_water + - (tbin->low_water >> 2) -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); - } - } - tbin->low_water = tbin->ncached; - tbin->high_water = tbin->ncached; - - tcache->next_gc_bin++; - if (tcache->next_gc_bin == nhbins) - tcache->next_gc_bin = 0; - tcache->ev_cnt = 0; - } + assert(tcache->ev_cnt <= TCACHE_GC_INCR); + if (tcache->ev_cnt == TCACHE_GC_INCR) + tcache_event_hard(tcache); } -JEMALLOC_INLINE void * +JEMALLOC_ALWAYS_INLINE void * tcache_alloc_easy(tcache_bin_t *tbin) { void *ret; - if (tbin->ncached == 0) + if (tbin->ncached == 0) { + tbin->low_water = -1; return (NULL); + } tbin->ncached--; - if (tbin->ncached < tbin->low_water) + if ((int)tbin->ncached < tbin->low_water) tbin->low_water = tbin->ncached; - ret = tbin->avail; - tbin->avail = *(void **)ret; + ret = tbin->avail[tbin->ncached]; return (ret); } -JEMALLOC_INLINE void * +JEMALLOC_ALWAYS_INLINE void * tcache_alloc_small(tcache_t *tcache, size_t size, bool zero) { void *ret; size_t binind; tcache_bin_t *tbin; - binind = small_size2bin[size]; - assert(binind < nbins); + binind = SMALL_SIZE2BIN(size); + assert(binind < NBINS); tbin = &tcache->tbins[binind]; ret = tcache_alloc_easy(tbin); if (ret == NULL) { @@ -234,29 +303,35 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero) if (ret == NULL) return (NULL); } - assert(arena_salloc(ret) == tcache->arena->bins[binind].reg_size); + assert(tcache_salloc(ret) == arena_bin_info[binind].reg_size); if (zero == false) { -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); -#endif - } else + if (config_fill) { + if (opt_junk) { + arena_alloc_junk_small(ret, + &arena_bin_info[binind], false); + } else if (opt_zero) + memset(ret, 0, size); + } + } else { + if (config_fill && opt_junk) { + arena_alloc_junk_small(ret, &arena_bin_info[binind], + true); + } + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); memset(ret, 0, size); + } + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); -#ifdef JEMALLOC_STATS - tbin->tstats.nrequests++; -#endif -#ifdef JEMALLOC_PROF - tcache->prof_accumbytes += tcache->arena->bins[binind].reg_size; -#endif + if (config_stats) + tbin->tstats.nrequests++; + if (config_prof) + tcache->prof_accumbytes += arena_bin_info[binind].reg_size; tcache_event(tcache); return (ret); } -JEMALLOC_INLINE void * +JEMALLOC_ALWAYS_INLINE void * tcache_alloc_large(tcache_t *tcache, size_t size, bool zero) { void *ret; @@ -265,7 +340,7 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero) size = PAGE_CEILING(size); assert(size <= tcache_maxclass); - binind = nbins + (size >> PAGE_SHIFT) - 1; + binind = NBINS + (size >> LG_PAGE) - 1; assert(binind < nhbins); tbin = &tcache->tbins[binind]; ret = tcache_alloc_easy(tbin); @@ -278,118 +353,86 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero) if (ret == NULL) return (NULL); } else { -#ifdef JEMALLOC_PROF - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); - size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >> - PAGE_SHIFT); - chunk->map[pageind-map_bias].bits &= ~CHUNK_MAP_CLASS_MASK; -#endif + if (config_prof && prof_promote && size == PAGE) { + arena_chunk_t *chunk = + (arena_chunk_t *)CHUNK_ADDR2BASE(ret); + size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >> + LG_PAGE); + arena_mapbits_large_binind_set(chunk, pageind, + BININD_INVALID); + } if (zero == false) { -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); -#endif - } else + if (config_fill) { + if (opt_junk) + memset(ret, 0xa5, size); + else if (opt_zero) + memset(ret, 0, size); + } + } else { + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); memset(ret, 0, size); + } + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); -#ifdef JEMALLOC_STATS - tbin->tstats.nrequests++; -#endif -#ifdef JEMALLOC_PROF - tcache->prof_accumbytes += size; -#endif + if (config_stats) + tbin->tstats.nrequests++; + if (config_prof) + tcache->prof_accumbytes += size; } tcache_event(tcache); return (ret); } -JEMALLOC_INLINE void -tcache_dalloc_small(tcache_t *tcache, void *ptr) +JEMALLOC_ALWAYS_INLINE void +tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind) { - arena_t *arena; - arena_chunk_t *chunk; - arena_run_t *run; - arena_bin_t *bin; tcache_bin_t *tbin; - size_t pageind, binind; - arena_chunk_map_t *mapelm; - - assert(arena_salloc(ptr) <= small_maxclass); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapelm = &chunk->map[pageind-map_bias]; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - (mapelm->bits >> PAGE_SHIFT)) << PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - bin = run->bin; - binind = ((uintptr_t)bin - (uintptr_t)&arena->bins) / - sizeof(arena_bin_t); - assert(binind < nbins); - -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ptr, 0x5a, bin->reg_size); -#endif + tcache_bin_info_t *tbin_info; + + assert(tcache_salloc(ptr) <= SMALL_MAXCLASS); + + if (config_fill && opt_junk) + arena_dalloc_junk_small(ptr, &arena_bin_info[binind]); tbin = &tcache->tbins[binind]; - if (tbin->ncached == tbin->ncached_max) { - tcache_bin_flush_small(tbin, binind, (tbin->ncached_max >> 1) -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); + tbin_info = &tcache_bin_info[binind]; + if (tbin->ncached == tbin_info->ncached_max) { + tcache_bin_flush_small(tbin, binind, (tbin_info->ncached_max >> + 1), tcache); } - assert(tbin->ncached < tbin->ncached_max); - *(void **)ptr = tbin->avail; - tbin->avail = ptr; + assert(tbin->ncached < tbin_info->ncached_max); + tbin->avail[tbin->ncached] = ptr; tbin->ncached++; - if (tbin->ncached > tbin->high_water) - tbin->high_water = tbin->ncached; tcache_event(tcache); } -JEMALLOC_INLINE void +JEMALLOC_ALWAYS_INLINE void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size) { - arena_t *arena; - arena_chunk_t *chunk; - size_t pageind, binind; + size_t binind; tcache_bin_t *tbin; + tcache_bin_info_t *tbin_info; assert((size & PAGE_MASK) == 0); - assert(arena_salloc(ptr) > small_maxclass); - assert(arena_salloc(ptr) <= tcache_maxclass); + assert(tcache_salloc(ptr) > SMALL_MAXCLASS); + assert(tcache_salloc(ptr) <= tcache_maxclass); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - binind = nbins + (size >> PAGE_SHIFT) - 1; + binind = NBINS + (size >> LG_PAGE) - 1; -#ifdef JEMALLOC_FILL - if (opt_junk) + if (config_fill && opt_junk) memset(ptr, 0x5a, size); -#endif tbin = &tcache->tbins[binind]; - if (tbin->ncached == tbin->ncached_max) { - tcache_bin_flush_large(tbin, binind, (tbin->ncached_max >> 1) -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); + tbin_info = &tcache_bin_info[binind]; + if (tbin->ncached == tbin_info->ncached_max) { + tcache_bin_flush_large(tbin, binind, (tbin_info->ncached_max >> + 1), tcache); } - assert(tbin->ncached < tbin->ncached_max); - *(void **)ptr = tbin->avail; - tbin->avail = ptr; + assert(tbin->ncached < tbin_info->ncached_max); + tbin->avail[tbin->ncached] = ptr; tbin->ncached++; - if (tbin->ncached > tbin->high_water) - tbin->high_water = tbin->ncached; tcache_event(tcache); } @@ -397,4 +440,3 @@ tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size) #endif /* JEMALLOC_H_INLINES */ /******************************************************************************/ -#endif /* JEMALLOC_TCACHE */ diff --git a/dep/jemalloc/include/jemalloc/internal/tsd.h b/dep/jemalloc/include/jemalloc/internal/tsd.h new file mode 100644 index 00000000000..0037cf35e70 --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/tsd.h @@ -0,0 +1,397 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +/* Maximum number of malloc_tsd users with cleanup functions. */ +#define MALLOC_TSD_CLEANUPS_MAX 8 + +typedef bool (*malloc_tsd_cleanup_t)(void); + +/* + * TLS/TSD-agnostic macro-based implementation of thread-specific data. There + * are four macros that support (at least) three use cases: file-private, + * library-private, and library-private inlined. Following is an example + * library-private tsd variable: + * + * In example.h: + * typedef struct { + * int x; + * int y; + * } example_t; + * #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0}) + * malloc_tsd_protos(, example, example_t *) + * malloc_tsd_externs(example, example_t *) + * In example.c: + * malloc_tsd_data(, example, example_t *, EX_INITIALIZER) + * malloc_tsd_funcs(, example, example_t *, EX_INITIALIZER, + * example_tsd_cleanup) + * + * The result is a set of generated functions, e.g.: + * + * bool example_tsd_boot(void) {...} + * example_t **example_tsd_get() {...} + * void example_tsd_set(example_t **val) {...} + * + * Note that all of the functions deal in terms of (a_type *) rather than + * (a_type) so that it is possible to support non-pointer types (unlike + * pthreads TSD). example_tsd_cleanup() is passed an (a_type *) pointer that is + * cast to (void *). This means that the cleanup function needs to cast *and* + * dereference the function argument, e.g.: + * + * void + * example_tsd_cleanup(void *arg) + * { + * example_t *example = *(example_t **)arg; + * + * [...] + * if ([want the cleanup function to be called again]) { + * example_tsd_set(&example); + * } + * } + * + * If example_tsd_set() is called within example_tsd_cleanup(), it will be + * called again. This is similar to how pthreads TSD destruction works, except + * that pthreads only calls the cleanup function again if the value was set to + * non-NULL. + */ + +/* malloc_tsd_protos(). */ +#define malloc_tsd_protos(a_attr, a_name, a_type) \ +a_attr bool \ +a_name##_tsd_boot(void); \ +a_attr a_type * \ +a_name##_tsd_get(void); \ +a_attr void \ +a_name##_tsd_set(a_type *val); + +/* malloc_tsd_externs(). */ +#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP +#define malloc_tsd_externs(a_name, a_type) \ +extern __thread a_type a_name##_tls; \ +extern __thread bool a_name##_initialized; \ +extern bool a_name##_booted; +#elif (defined(JEMALLOC_TLS)) +#define malloc_tsd_externs(a_name, a_type) \ +extern __thread a_type a_name##_tls; \ +extern pthread_key_t a_name##_tsd; \ +extern bool a_name##_booted; +#elif (defined(_WIN32)) +#define malloc_tsd_externs(a_name, a_type) \ +extern DWORD a_name##_tsd; \ +extern bool a_name##_booted; +#else +#define malloc_tsd_externs(a_name, a_type) \ +extern pthread_key_t a_name##_tsd; \ +extern bool a_name##_booted; +#endif + +/* malloc_tsd_data(). */ +#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP +#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ +a_attr __thread a_type JEMALLOC_TLS_MODEL \ + a_name##_tls = a_initializer; \ +a_attr __thread bool JEMALLOC_TLS_MODEL \ + a_name##_initialized = false; \ +a_attr bool a_name##_booted = false; +#elif (defined(JEMALLOC_TLS)) +#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ +a_attr __thread a_type JEMALLOC_TLS_MODEL \ + a_name##_tls = a_initializer; \ +a_attr pthread_key_t a_name##_tsd; \ +a_attr bool a_name##_booted = false; +#elif (defined(_WIN32)) +#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ +a_attr DWORD a_name##_tsd; \ +a_attr bool a_name##_booted = false; +#else +#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ +a_attr pthread_key_t a_name##_tsd; \ +a_attr bool a_name##_booted = false; +#endif + +/* malloc_tsd_funcs(). */ +#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP +#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ + a_cleanup) \ +/* Initialization/cleanup. */ \ +a_attr bool \ +a_name##_tsd_cleanup_wrapper(void) \ +{ \ + \ + if (a_name##_initialized) { \ + a_name##_initialized = false; \ + a_cleanup(&a_name##_tls); \ + } \ + return (a_name##_initialized); \ +} \ +a_attr bool \ +a_name##_tsd_boot(void) \ +{ \ + \ + if (a_cleanup != malloc_tsd_no_cleanup) { \ + malloc_tsd_cleanup_register( \ + &a_name##_tsd_cleanup_wrapper); \ + } \ + a_name##_booted = true; \ + return (false); \ +} \ +/* Get/set. */ \ +a_attr a_type * \ +a_name##_tsd_get(void) \ +{ \ + \ + assert(a_name##_booted); \ + return (&a_name##_tls); \ +} \ +a_attr void \ +a_name##_tsd_set(a_type *val) \ +{ \ + \ + assert(a_name##_booted); \ + a_name##_tls = (*val); \ + if (a_cleanup != malloc_tsd_no_cleanup) \ + a_name##_initialized = true; \ +} +#elif (defined(JEMALLOC_TLS)) +#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ + a_cleanup) \ +/* Initialization/cleanup. */ \ +a_attr bool \ +a_name##_tsd_boot(void) \ +{ \ + \ + if (a_cleanup != malloc_tsd_no_cleanup) { \ + if (pthread_key_create(&a_name##_tsd, a_cleanup) != 0) \ + return (true); \ + } \ + a_name##_booted = true; \ + return (false); \ +} \ +/* Get/set. */ \ +a_attr a_type * \ +a_name##_tsd_get(void) \ +{ \ + \ + assert(a_name##_booted); \ + return (&a_name##_tls); \ +} \ +a_attr void \ +a_name##_tsd_set(a_type *val) \ +{ \ + \ + assert(a_name##_booted); \ + a_name##_tls = (*val); \ + if (a_cleanup != malloc_tsd_no_cleanup) { \ + if (pthread_setspecific(a_name##_tsd, \ + (void *)(&a_name##_tls))) { \ + malloc_write("<jemalloc>: Error" \ + " setting TSD for "#a_name"\n"); \ + if (opt_abort) \ + abort(); \ + } \ + } \ +} +#elif (defined(_WIN32)) +#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ + a_cleanup) \ +/* Data structure. */ \ +typedef struct { \ + bool initialized; \ + a_type val; \ +} a_name##_tsd_wrapper_t; \ +/* Initialization/cleanup. */ \ +a_attr bool \ +a_name##_tsd_cleanup_wrapper(void) \ +{ \ + a_name##_tsd_wrapper_t *wrapper; \ + \ + wrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd); \ + if (wrapper == NULL) \ + return (false); \ + if (a_cleanup != malloc_tsd_no_cleanup && \ + wrapper->initialized) { \ + a_type val = wrapper->val; \ + a_type tsd_static_data = a_initializer; \ + wrapper->initialized = false; \ + wrapper->val = tsd_static_data; \ + a_cleanup(&val); \ + if (wrapper->initialized) { \ + /* Trigger another cleanup round. */ \ + return (true); \ + } \ + } \ + malloc_tsd_dalloc(wrapper); \ + return (false); \ +} \ +a_attr bool \ +a_name##_tsd_boot(void) \ +{ \ + \ + a_name##_tsd = TlsAlloc(); \ + if (a_name##_tsd == TLS_OUT_OF_INDEXES) \ + return (true); \ + if (a_cleanup != malloc_tsd_no_cleanup) { \ + malloc_tsd_cleanup_register( \ + &a_name##_tsd_cleanup_wrapper); \ + } \ + a_name##_booted = true; \ + return (false); \ +} \ +/* Get/set. */ \ +a_attr a_name##_tsd_wrapper_t * \ +a_name##_tsd_get_wrapper(void) \ +{ \ + a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \ + TlsGetValue(a_name##_tsd); \ + \ + if (wrapper == NULL) { \ + wrapper = (a_name##_tsd_wrapper_t *) \ + malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \ + if (wrapper == NULL) { \ + malloc_write("<jemalloc>: Error allocating" \ + " TSD for "#a_name"\n"); \ + abort(); \ + } else { \ + static a_type tsd_static_data = a_initializer; \ + wrapper->initialized = false; \ + wrapper->val = tsd_static_data; \ + } \ + if (!TlsSetValue(a_name##_tsd, (void *)wrapper)) { \ + malloc_write("<jemalloc>: Error setting" \ + " TSD for "#a_name"\n"); \ + abort(); \ + } \ + } \ + return (wrapper); \ +} \ +a_attr a_type * \ +a_name##_tsd_get(void) \ +{ \ + a_name##_tsd_wrapper_t *wrapper; \ + \ + assert(a_name##_booted); \ + wrapper = a_name##_tsd_get_wrapper(); \ + return (&wrapper->val); \ +} \ +a_attr void \ +a_name##_tsd_set(a_type *val) \ +{ \ + a_name##_tsd_wrapper_t *wrapper; \ + \ + assert(a_name##_booted); \ + wrapper = a_name##_tsd_get_wrapper(); \ + wrapper->val = *(val); \ + if (a_cleanup != malloc_tsd_no_cleanup) \ + wrapper->initialized = true; \ +} +#else +#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ + a_cleanup) \ +/* Data structure. */ \ +typedef struct { \ + bool initialized; \ + a_type val; \ +} a_name##_tsd_wrapper_t; \ +/* Initialization/cleanup. */ \ +a_attr void \ +a_name##_tsd_cleanup_wrapper(void *arg) \ +{ \ + a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)arg;\ + \ + if (a_cleanup != malloc_tsd_no_cleanup && \ + wrapper->initialized) { \ + wrapper->initialized = false; \ + a_cleanup(&wrapper->val); \ + if (wrapper->initialized) { \ + /* Trigger another cleanup round. */ \ + if (pthread_setspecific(a_name##_tsd, \ + (void *)wrapper)) { \ + malloc_write("<jemalloc>: Error" \ + " setting TSD for "#a_name"\n"); \ + if (opt_abort) \ + abort(); \ + } \ + return; \ + } \ + } \ + malloc_tsd_dalloc(wrapper); \ +} \ +a_attr bool \ +a_name##_tsd_boot(void) \ +{ \ + \ + if (pthread_key_create(&a_name##_tsd, \ + a_name##_tsd_cleanup_wrapper) != 0) \ + return (true); \ + a_name##_booted = true; \ + return (false); \ +} \ +/* Get/set. */ \ +a_attr a_name##_tsd_wrapper_t * \ +a_name##_tsd_get_wrapper(void) \ +{ \ + a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \ + pthread_getspecific(a_name##_tsd); \ + \ + if (wrapper == NULL) { \ + wrapper = (a_name##_tsd_wrapper_t *) \ + malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \ + if (wrapper == NULL) { \ + malloc_write("<jemalloc>: Error allocating" \ + " TSD for "#a_name"\n"); \ + abort(); \ + } else { \ + static a_type tsd_static_data = a_initializer; \ + wrapper->initialized = false; \ + wrapper->val = tsd_static_data; \ + } \ + if (pthread_setspecific(a_name##_tsd, \ + (void *)wrapper)) { \ + malloc_write("<jemalloc>: Error setting" \ + " TSD for "#a_name"\n"); \ + abort(); \ + } \ + } \ + return (wrapper); \ +} \ +a_attr a_type * \ +a_name##_tsd_get(void) \ +{ \ + a_name##_tsd_wrapper_t *wrapper; \ + \ + assert(a_name##_booted); \ + wrapper = a_name##_tsd_get_wrapper(); \ + return (&wrapper->val); \ +} \ +a_attr void \ +a_name##_tsd_set(a_type *val) \ +{ \ + a_name##_tsd_wrapper_t *wrapper; \ + \ + assert(a_name##_booted); \ + wrapper = a_name##_tsd_get_wrapper(); \ + wrapper->val = *(val); \ + if (a_cleanup != malloc_tsd_no_cleanup) \ + wrapper->initialized = true; \ +} +#endif + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +void *malloc_tsd_malloc(size_t size); +void malloc_tsd_dalloc(void *wrapper); +void malloc_tsd_no_cleanup(void *); +void malloc_tsd_cleanup_register(bool (*f)(void)); +void malloc_tsd_boot(void); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/internal/util.h b/dep/jemalloc/include/jemalloc/internal/util.h new file mode 100644 index 00000000000..8479693631a --- /dev/null +++ b/dep/jemalloc/include/jemalloc/internal/util.h @@ -0,0 +1,160 @@ +/******************************************************************************/ +#ifdef JEMALLOC_H_TYPES + +/* Size of stack-allocated buffer passed to buferror(). */ +#define BUFERROR_BUF 64 + +/* + * Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be + * large enough for all possible uses within jemalloc. + */ +#define MALLOC_PRINTF_BUFSIZE 4096 + +/* + * Wrap a cpp argument that contains commas such that it isn't broken up into + * multiple arguments. + */ +#define JEMALLOC_CONCAT(...) __VA_ARGS__ + +/* + * Silence compiler warnings due to uninitialized values. This is used + * wherever the compiler fails to recognize that the variable is never used + * uninitialized. + */ +#ifdef JEMALLOC_CC_SILENCE +# define JEMALLOC_CC_SILENCE_INIT(v) = v +#else +# define JEMALLOC_CC_SILENCE_INIT(v) +#endif + +/* + * Define a custom assert() in order to reduce the chances of deadlock during + * assertion failure. + */ +#ifndef assert +#define assert(e) do { \ + if (config_debug && !(e)) { \ + malloc_printf( \ + "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \ + __FILE__, __LINE__, #e); \ + abort(); \ + } \ +} while (0) +#endif + +/* Use to assert a particular configuration, e.g., cassert(config_debug). */ +#define cassert(c) do { \ + if ((c) == false) \ + assert(false); \ +} while (0) + +#ifndef not_reached +#define not_reached() do { \ + if (config_debug) { \ + malloc_printf( \ + "<jemalloc>: %s:%d: Unreachable code reached\n", \ + __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) +#endif + +#ifndef not_implemented +#define not_implemented() do { \ + if (config_debug) { \ + malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \ + __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) +#endif + +#define assert_not_implemented(e) do { \ + if (config_debug && !(e)) \ + not_implemented(); \ +} while (0) + +#endif /* JEMALLOC_H_TYPES */ +/******************************************************************************/ +#ifdef JEMALLOC_H_STRUCTS + +#endif /* JEMALLOC_H_STRUCTS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_EXTERNS + +int buferror(char *buf, size_t buflen); +uintmax_t malloc_strtoumax(const char *nptr, char **endptr, int base); +void malloc_write(const char *s); + +/* + * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating + * point math. + */ +int malloc_vsnprintf(char *str, size_t size, const char *format, + va_list ap); +int malloc_snprintf(char *str, size_t size, const char *format, ...) + JEMALLOC_ATTR(format(printf, 3, 4)); +void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, va_list ap); +void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque, + const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4)); +void malloc_printf(const char *format, ...) + JEMALLOC_ATTR(format(printf, 1, 2)); + +#endif /* JEMALLOC_H_EXTERNS */ +/******************************************************************************/ +#ifdef JEMALLOC_H_INLINES + +#ifndef JEMALLOC_ENABLE_INLINE +size_t pow2_ceil(size_t x); +void malloc_write(const char *s); +void set_errno(int errnum); +int get_errno(void); +#endif + +#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_)) +/* Compute the smallest power of 2 that is >= x. */ +JEMALLOC_INLINE size_t +pow2_ceil(size_t x) +{ + + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; +#if (LG_SIZEOF_PTR == 3) + x |= x >> 32; +#endif + x++; + return (x); +} + +/* Sets error code */ +JEMALLOC_INLINE void +set_errno(int errnum) +{ + +#ifdef _WIN32 + SetLastError(errnum); +#else + errno = errnum; +#endif +} + +/* Get last error code */ +JEMALLOC_INLINE int +get_errno(void) +{ + +#ifdef _WIN32 + return (GetLastError()); +#else + return (errno); +#endif +} +#endif + +#endif /* JEMALLOC_H_INLINES */ +/******************************************************************************/ diff --git a/dep/jemalloc/include/jemalloc/jemalloc.h b/dep/jemalloc/include/jemalloc/jemalloc.h index 287dac46ed2..946c73b75e5 100644 --- a/dep/jemalloc/include/jemalloc/jemalloc.h +++ b/dep/jemalloc/include/jemalloc/jemalloc.h @@ -7,19 +7,17 @@ extern "C" { #include <limits.h> #include <strings.h> -#define JEMALLOC_VERSION "2.1.0-0-g1c4b088b08d3bc7617a34387e196ce03716160bf" -#define JEMALLOC_VERSION_MAJOR 2 -#define JEMALLOC_VERSION_MINOR 1 -#define JEMALLOC_VERSION_BUGFIX 0 +#define JEMALLOC_VERSION "3.3.1-0-g9ef9d9e8c271cdf14f664b871a8f98c827714784" +#define JEMALLOC_VERSION_MAJOR 3 +#define JEMALLOC_VERSION_MINOR 3 +#define JEMALLOC_VERSION_BUGFIX 1 #define JEMALLOC_VERSION_NREV 0 -#define JEMALLOC_VERSION_GID "1c4b088b08d3bc7617a34387e196ce03716160bf" +#define JEMALLOC_VERSION_GID "9ef9d9e8c271cdf14f664b871a8f98c827714784" #include "jemalloc_defs.h" -#ifndef JEMALLOC_P -# define JEMALLOC_P(s) s -#endif -#define ALLOCM_LG_ALIGN ((int)0x3f) +#ifdef JEMALLOC_EXPERIMENTAL +#define ALLOCM_LG_ALIGN(la) (la) #if LG_SIZEOF_PTR == 2 #define ALLOCM_ALIGN(a) (ffs(a)-1) #else @@ -27,38 +25,131 @@ extern "C" { #endif #define ALLOCM_ZERO ((int)0x40) #define ALLOCM_NO_MOVE ((int)0x80) +/* Bias arena index bits so that 0 encodes "ALLOCM_ARENA() unspecified". */ +#define ALLOCM_ARENA(a) ((int)(((a)+1) << 8)) #define ALLOCM_SUCCESS 0 #define ALLOCM_ERR_OOM 1 #define ALLOCM_ERR_NOT_MOVED 2 +#endif -extern const char *JEMALLOC_P(malloc_conf); -extern void (*JEMALLOC_P(malloc_message))(void *, const char *); +/* + * The je_ prefix on the following public symbol declarations is an artifact of + * namespace management, and should be omitted in application code unless + * JEMALLOC_NO_DEMANGLE is defined (see below). + */ +extern JEMALLOC_EXPORT const char *je_malloc_conf; +extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, + const char *s); -void *JEMALLOC_P(malloc)(size_t size) JEMALLOC_ATTR(malloc); -void *JEMALLOC_P(calloc)(size_t num, size_t size) JEMALLOC_ATTR(malloc); -int JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size) - JEMALLOC_ATTR(nonnull(1)); -void *JEMALLOC_P(realloc)(void *ptr, size_t size); -void JEMALLOC_P(free)(void *ptr); +JEMALLOC_EXPORT void *je_malloc(size_t size) JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT void *je_calloc(size_t num, size_t size) + JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT int je_posix_memalign(void **memptr, size_t alignment, + size_t size) JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT void *je_aligned_alloc(size_t alignment, size_t size) + JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT void *je_realloc(void *ptr, size_t size); +JEMALLOC_EXPORT void je_free(void *ptr); -size_t JEMALLOC_P(malloc_usable_size)(const void *ptr); -void JEMALLOC_P(malloc_stats_print)(void (*write_cb)(void *, const char *), - void *cbopaque, const char *opts); -int JEMALLOC_P(mallctl)(const char *name, void *oldp, size_t *oldlenp, - void *newp, size_t newlen); -int JEMALLOC_P(mallctlnametomib)(const char *name, size_t *mibp, - size_t *miblenp); -int JEMALLOC_P(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, +#ifdef JEMALLOC_OVERRIDE_MEMALIGN +JEMALLOC_EXPORT void * je_memalign(size_t alignment, size_t size) + JEMALLOC_ATTR(malloc); +#endif + +#ifdef JEMALLOC_OVERRIDE_VALLOC +JEMALLOC_EXPORT void * je_valloc(size_t size) JEMALLOC_ATTR(malloc); +#endif + +JEMALLOC_EXPORT size_t je_malloc_usable_size( + JEMALLOC_USABLE_SIZE_CONST void *ptr); +JEMALLOC_EXPORT void je_malloc_stats_print(void (*write_cb)(void *, + const char *), void *je_cbopaque, const char *opts); +JEMALLOC_EXPORT int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen); +JEMALLOC_EXPORT int je_mallctlnametomib(const char *name, size_t *mibp, + size_t *miblenp); +JEMALLOC_EXPORT int je_mallctlbymib(const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen); -int JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags) - JEMALLOC_ATTR(nonnull(1)); -int JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, +#ifdef JEMALLOC_EXPERIMENTAL +JEMALLOC_EXPORT int je_allocm(void **ptr, size_t *rsize, size_t size, + int flags) JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT int je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags) JEMALLOC_ATTR(nonnull(1)); -int JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags) +JEMALLOC_EXPORT int je_sallocm(const void *ptr, size_t *rsize, int flags) JEMALLOC_ATTR(nonnull(1)); -int JEMALLOC_P(dallocm)(void *ptr, int flags) JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT int je_dallocm(void *ptr, int flags) + JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT int je_nallocm(size_t *rsize, size_t size, int flags); +#endif + +/* + * By default application code must explicitly refer to mangled symbol names, + * so that it is possible to use jemalloc in conjunction with another allocator + * in the same application. Define JEMALLOC_MANGLE in order to cause automatic + * name mangling that matches the API prefixing that happened as a result of + * --with-mangling and/or --with-jemalloc-prefix configuration settings. + */ +#ifdef JEMALLOC_MANGLE +#ifndef JEMALLOC_NO_DEMANGLE +#define JEMALLOC_NO_DEMANGLE +#endif +#define malloc_conf je_malloc_conf +#define malloc_message je_malloc_message +#define malloc je_malloc +#define calloc je_calloc +#define posix_memalign je_posix_memalign +#define aligned_alloc je_aligned_alloc +#define realloc je_realloc +#define free je_free +#define malloc_usable_size je_malloc_usable_size +#define malloc_stats_print je_malloc_stats_print +#define mallctl je_mallctl +#define mallctlnametomib je_mallctlnametomib +#define mallctlbymib je_mallctlbymib +#define memalign je_memalign +#define valloc je_valloc +#ifdef JEMALLOC_EXPERIMENTAL +#define allocm je_allocm +#define rallocm je_rallocm +#define sallocm je_sallocm +#define dallocm je_dallocm +#define nallocm je_nallocm +#endif +#endif + +/* + * The je_* macros can be used as stable alternative names for the public + * jemalloc API if JEMALLOC_NO_DEMANGLE is defined. This is primarily meant + * for use in jemalloc itself, but it can be used by application code to + * provide isolation from the name mangling specified via --with-mangling + * and/or --with-jemalloc-prefix. + */ +#ifndef JEMALLOC_NO_DEMANGLE +#undef je_malloc_conf +#undef je_malloc_message +#undef je_malloc +#undef je_calloc +#undef je_posix_memalign +#undef je_aligned_alloc +#undef je_realloc +#undef je_free +#undef je_malloc_usable_size +#undef je_malloc_stats_print +#undef je_mallctl +#undef je_mallctlnametomib +#undef je_mallctlbymib +#undef je_memalign +#undef je_valloc +#ifdef JEMALLOC_EXPERIMENTAL +#undef je_allocm +#undef je_rallocm +#undef je_sallocm +#undef je_dallocm +#undef je_nallocm +#endif +#endif #ifdef __cplusplus }; diff --git a/dep/jemalloc/include/jemalloc/jemalloc_defs.h b/dep/jemalloc/include/jemalloc/jemalloc_defs.h deleted file mode 100644 index a641b56da03..00000000000 --- a/dep/jemalloc/include/jemalloc/jemalloc_defs.h +++ /dev/null @@ -1,141 +0,0 @@ -/* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */ -#ifndef JEMALLOC_DEFS_H_ -#define JEMALLOC_DEFS_H_ - -/* - * If JEMALLOC_PREFIX is defined, it will cause all public APIs to be prefixed. - * This makes it possible, with some care, to use multiple allocators - * simultaneously. - * - * In many cases it is more convenient to manually prefix allocator function - * calls than to let macros do it automatically, particularly when using - * multiple allocators simultaneously. Define JEMALLOC_MANGLE before - * #include'ing jemalloc.h in order to cause name mangling that corresponds to - * the API prefixing. - */ -/* #undef JEMALLOC_PREFIX */ -/* #undef JEMALLOC_CPREFIX */ -#if (defined(JEMALLOC_PREFIX) && defined(JEMALLOC_MANGLE)) -/* #undef JEMALLOC_P */ -#endif - -/* - * Hyper-threaded CPUs may need a special instruction inside spin loops in - * order to yield to another virtual CPU. - */ -#define CPU_SPINWAIT __asm__ volatile("pause") - -/* Defined if __attribute__((...)) syntax is supported. */ -#define JEMALLOC_HAVE_ATTR -#ifdef JEMALLOC_HAVE_ATTR -# define JEMALLOC_ATTR(s) __attribute__((s)) -#else -# define JEMALLOC_ATTR(s) -#endif - -/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */ -/* #undef JEMALLOC_CC_SILENCE */ - -/* - * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables - * inline functions. - */ -/* #undef JEMALLOC_DEBUG */ - -/* JEMALLOC_STATS enables statistics calculation. */ -/* #undef JEMALLOC_STATS */ - -/* JEMALLOC_PROF enables allocation profiling. */ -/* #undef JEMALLOC_PROF */ - -/* Use libunwind for profile backtracing if defined. */ -/* #undef JEMALLOC_PROF_LIBUNWIND */ - -/* Use libgcc for profile backtracing if defined. */ -/* #undef JEMALLOC_PROF_LIBGCC */ - -/* - * JEMALLOC_TINY enables support for tiny objects, which are smaller than one - * quantum. - */ -/* #undef JEMALLOC_TINY */ - -/* - * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects. - * This makes it possible to allocate/deallocate objects without any locking - * when the cache is in the steady state. - */ -/* #undef JEMALLOC_TCACHE */ - -/* - * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage - * segment (DSS). - */ -/* #undef JEMALLOC_DSS */ - -/* JEMALLOC_SWAP enables mmap()ed swap file support. */ -/* #undef JEMALLOC_SWAP */ - -/* Support memory filling (junk/zero). */ -/* #undef JEMALLOC_FILL */ - -/* Support optional abort() on OOM. */ -/* #undef JEMALLOC_XMALLOC */ - -/* Support SYSV semantics. */ -/* #undef JEMALLOC_SYSV */ - -/* Support lazy locking (avoid locking unless a second thread is launched). */ -/* #undef JEMALLOC_LAZY_LOCK */ - -/* Determine page size at run time if defined. */ -/* #undef DYNAMIC_PAGE_SHIFT */ - -/* One page is 2^STATIC_PAGE_SHIFT bytes. */ -#define STATIC_PAGE_SHIFT 12 - -/* TLS is used to map arenas and magazine caches to threads. */ -/* #undef NO_TLS */ - -/* - * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside - * within jemalloc-owned chunks before dereferencing them. - */ -/* #undef JEMALLOC_IVSALLOC */ - -/* - * Define overrides for non-standard allocator-related functions if they - * are present on the system. - */ -#define JEMALLOC_OVERRIDE_MEMALIGN 1 -#define JEMALLOC_OVERRIDE_VALLOC 1 - -/* - * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. - */ -/* #undef JEMALLOC_ZONE */ -/* #undef JEMALLOC_ZONE_VERSION */ - -/* If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). */ -#define JEMALLOC_MREMAP_FIXED 1 - -/* - * Methods for purging unused pages differ between operating systems. - * - * madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages, - * such that new pages will be demand-zeroed if - * the address region is later touched. - * madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being - * unused, such that they will be discarded rather - * than swapped out. - */ -#define JEMALLOC_PURGE_MADVISE_DONTNEED 1 -/* #undef JEMALLOC_PURGE_MADVISE_FREE */ - -/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ -#define LG_SIZEOF_PTR 2 - -/* sizeof(int) == 2^LG_SIZEOF_INT. */ -#define LG_SIZEOF_INT 2 - -#endif /* JEMALLOC_DEFS_H_ */ diff --git a/dep/jemalloc/include/msvc_compat/inttypes.h b/dep/jemalloc/include/msvc_compat/inttypes.h new file mode 100644 index 00000000000..a4e6b75cb91 --- /dev/null +++ b/dep/jemalloc/include/msvc_compat/inttypes.h @@ -0,0 +1,313 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +#ifdef _WIN64 +# define __PRI64_PREFIX "l" +# define __PRIPTR_PREFIX "l" +#else +# define __PRI64_PREFIX "ll" +# define __PRIPTR_PREFIX +#endif + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "d" +#define PRIi32 "i" +#define PRIdLEAST32 "d" +#define PRIiLEAST32 "i" +#define PRIdFAST32 "d" +#define PRIiFAST32 "i" + +#define PRId64 __PRI64_PREFIX "d" +#define PRIi64 __PRI64_PREFIX "i" +#define PRIdLEAST64 __PRI64_PREFIX "d" +#define PRIiLEAST64 __PRI64_PREFIX "i" +#define PRIdFAST64 __PRI64_PREFIX "d" +#define PRIiFAST64 __PRI64_PREFIX "i" + +#define PRIdMAX __PRI64_PREFIX "d" +#define PRIiMAX __PRI64_PREFIX "i" + +#define PRIdPTR __PRIPTR_PREFIX "d" +#define PRIiPTR __PRIPTR_PREFIX "i" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "o" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define PRIoLEAST32 "o" +#define PRIuLEAST32 "u" +#define PRIxLEAST32 "x" +#define PRIXLEAST32 "X" +#define PRIoFAST32 "o" +#define PRIuFAST32 "u" +#define PRIxFAST32 "x" +#define PRIXFAST32 "X" + +#define PRIo64 __PRI64_PREFIX "o" +#define PRIu64 __PRI64_PREFIX "u" +#define PRIx64 __PRI64_PREFIX "x" +#define PRIX64 __PRI64_PREFIX "X" +#define PRIoLEAST64 __PRI64_PREFIX "o" +#define PRIuLEAST64 __PRI64_PREFIX "u" +#define PRIxLEAST64 __PRI64_PREFIX "x" +#define PRIXLEAST64 __PRI64_PREFIX "X" +#define PRIoFAST64 __PRI64_PREFIX "o" +#define PRIuFAST64 __PRI64_PREFIX "u" +#define PRIxFAST64 __PRI64_PREFIX "x" +#define PRIXFAST64 __PRI64_PREFIX "X" + +#define PRIoMAX __PRI64_PREFIX "o" +#define PRIuMAX __PRI64_PREFIX "u" +#define PRIxMAX __PRI64_PREFIX "x" +#define PRIXMAX __PRI64_PREFIX "X" + +#define PRIoPTR __PRIPTR_PREFIX "o" +#define PRIuPTR __PRIPTR_PREFIX "u" +#define PRIxPTR __PRIPTR_PREFIX "x" +#define PRIXPTR __PRIPTR_PREFIX "X" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/dep/jemalloc/include/msvc_compat/stdbool.h b/dep/jemalloc/include/msvc_compat/stdbool.h new file mode 100644 index 00000000000..da9ee8b809b --- /dev/null +++ b/dep/jemalloc/include/msvc_compat/stdbool.h @@ -0,0 +1,16 @@ +#ifndef stdbool_h +#define stdbool_h + +#include <wtypes.h> + +/* MSVC doesn't define _Bool or bool in C, but does have BOOL */ +/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */ +typedef BOOL _Bool; + +#define bool _Bool +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif /* stdbool_h */ diff --git a/dep/jemalloc/include/msvc_compat/stdint.h b/dep/jemalloc/include/msvc_compat/stdint.h new file mode 100644 index 00000000000..d02608a5972 --- /dev/null +++ b/dep/jemalloc/include/msvc_compat/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include <wchar.h> +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/dep/jemalloc/include/msvc_compat/strings.h b/dep/jemalloc/include/msvc_compat/strings.h new file mode 100644 index 00000000000..c84975b6b8e --- /dev/null +++ b/dep/jemalloc/include/msvc_compat/strings.h @@ -0,0 +1,23 @@ +#ifndef strings_h +#define strings_h + +/* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided + * for both */ +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +static __forceinline int ffsl(long x) +{ + unsigned long i; + + if (_BitScanForward(&i, x)) + return (i + 1); + return (0); +} + +static __forceinline int ffs(int x) +{ + + return (ffsl(x)); +} + +#endif diff --git a/dep/jemalloc/jemalloc_defs.h.in.cmake b/dep/jemalloc/jemalloc_defs.h.in.cmake new file mode 100644 index 00000000000..9fdf53546e3 --- /dev/null +++ b/dep/jemalloc/jemalloc_defs.h.in.cmake @@ -0,0 +1,268 @@ +/* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */ +/* + * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all + * public APIs to be prefixed. This makes it possible, with some care, to use + * multiple allocators simultaneously. + */ +/* #undef JEMALLOC_PREFIX */ +/* #undef JEMALLOC_CPREFIX */ + +/* + * Name mangling for public symbols is controlled by --with-mangling and + * --with-jemalloc-prefix. With default settings the je_ prefix is stripped by + * these macro definitions. + */ +#define je_malloc_conf malloc_conf +#define je_malloc_message malloc_message +#define je_malloc malloc +#define je_calloc calloc +#define je_posix_memalign posix_memalign +#define je_aligned_alloc aligned_alloc +#define je_realloc realloc +#define je_free free +#define je_malloc_usable_size malloc_usable_size +#define je_malloc_stats_print malloc_stats_print +#define je_mallctl mallctl +#define je_mallctlnametomib mallctlnametomib +#define je_mallctlbymib mallctlbymib +#define je_memalign memalign +#define je_valloc valloc +#define je_allocm allocm +#define je_rallocm rallocm +#define je_sallocm sallocm +#define je_dallocm dallocm +#define je_nallocm nallocm + +/* + * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs. + * For shared libraries, symbol visibility mechanisms prevent these symbols + * from being exported, but for static libraries, naming collisions are a real + * possibility. + */ +#define JEMALLOC_PRIVATE_NAMESPACE "" +#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix + +/* + * Hyper-threaded CPUs may need a special instruction inside spin loops in + * order to yield to another virtual CPU. + */ +#define CPU_SPINWAIT __asm__ volatile("pause") + +/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */ +/* #undef JEMALLOC_ATOMIC9 */ + +/* + * Defined if OSAtomic*() functions are available, as provided by Darwin, and + * documented in the atomic(3) manual page. + */ +/* #undef JEMALLOC_OSATOMIC */ + +/* + * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and + * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite + * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the + * functions are defined in libgcc instead of being inlines) + */ +/* #undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4 */ + +/* + * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and + * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite + * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the + * functions are defined in libgcc instead of being inlines) + */ +/* #undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8 */ + +/* + * Defined if OSSpin*() functions are available, as provided by Darwin, and + * documented in the spinlock(3) manual page. + */ +/* #undef JEMALLOC_OSSPIN */ + +/* + * Defined if _malloc_thread_cleanup() exists. At least in the case of + * FreeBSD, pthread_key_create() allocates, which if used during malloc + * bootstrapping will cause recursion into the pthreads library. Therefore, if + * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in + * malloc_tsd. + */ +/* #undef JEMALLOC_MALLOC_THREAD_CLEANUP */ + +/* + * Defined if threaded initialization is known to be safe on this platform. + * Among other things, it must be possible to initialize a mutex without + * triggering allocation in order for threaded allocation to be safe. + */ +#define JEMALLOC_THREADED_INIT + +/* + * Defined if the pthreads implementation defines + * _pthread_mutex_init_calloc_cb(), in which case the function is used in order + * to avoid recursive allocation during mutex initialization. + */ +/* #undef JEMALLOC_MUTEX_INIT_CB */ + +/* Defined if __attribute__((...)) syntax is supported. */ +#define JEMALLOC_HAVE_ATTR +#ifdef JEMALLOC_HAVE_ATTR +# define JEMALLOC_ATTR(s) __attribute__((s)) +# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) +# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) +# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) +# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) +#elif _MSC_VER +# define JEMALLOC_ATTR(s) +# ifdef DLLEXPORT +# define JEMALLOC_EXPORT __declspec(dllexport) +# else +# define JEMALLOC_EXPORT __declspec(dllimport) +# endif +# define JEMALLOC_ALIGNED(s) __declspec(align(s)) +# define JEMALLOC_SECTION(s) __declspec(allocate(s)) +# define JEMALLOC_NOINLINE __declspec(noinline) +#else +# define JEMALLOC_ATTR(s) +# define JEMALLOC_EXPORT +# define JEMALLOC_ALIGNED(s) +# define JEMALLOC_SECTION(s) +# define JEMALLOC_NOINLINE +#endif + +/* Defined if sbrk() is supported. */ +#define JEMALLOC_HAVE_SBRK + +/* Non-empty if the tls_model attribute is supported. */ +#define JEMALLOC_TLS_MODEL @JEM_TLSMODEL@ + +/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */ +/* #undef JEMALLOC_CC_SILENCE */ + +/* + * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables + * inline functions. + */ +/* #undef JEMALLOC_DEBUG */ + +/* JEMALLOC_STATS enables statistics calculation. */ +#define JEMALLOC_STATS + +/* JEMALLOC_PROF enables allocation profiling. */ +/* #undef JEMALLOC_PROF */ + +/* Use libunwind for profile backtracing if defined. */ +/* #undef JEMALLOC_PROF_LIBUNWIND */ + +/* Use libgcc for profile backtracing if defined. */ +/* #undef JEMALLOC_PROF_LIBGCC */ + +/* Use gcc intrinsics for profile backtracing if defined. */ +/* #undef JEMALLOC_PROF_GCC */ + +/* + * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects. + * This makes it possible to allocate/deallocate objects without any locking + * when the cache is in the steady state. + */ +#define JEMALLOC_TCACHE + +/* + * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage + * segment (DSS). + */ +/* #undef JEMALLOC_DSS */ + +/* Support memory filling (junk/zero/quarantine/redzone). */ +#define JEMALLOC_FILL + +/* Support the experimental API. */ +#define JEMALLOC_EXPERIMENTAL + +/* Support utrace(2)-based tracing. */ +/* #undef JEMALLOC_UTRACE */ + +/* Support Valgrind. */ +/* #undef JEMALLOC_VALGRIND */ + +/* Support optional abort() on OOM. */ +/* #undef JEMALLOC_XMALLOC */ + +/* Support lazy locking (avoid locking unless a second thread is launched). */ +/* #undef JEMALLOC_LAZY_LOCK */ + +/* One page is 2^STATIC_PAGE_SHIFT bytes. */ +#define STATIC_PAGE_SHIFT 12 + +/* + * If defined, use munmap() to unmap freed chunks, rather than storing them for + * later reuse. This is disabled by default on Linux because common sequences + * of mmap()/munmap() calls will cause virtual memory map holes. + */ +/* #undef JEMALLOC_MUNMAP */ + +/* + * If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). This is + * disabled by default because it is Linux-specific and it will cause virtual + * memory map holes, much like munmap(2) does. + */ +/* #undef JEMALLOC_MREMAP */ + +/* TLS is used to map arenas and magazine caches to threads. */ +#define JEMALLOC_TLS + +/* + * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside + * within jemalloc-owned chunks before dereferencing them. + */ +/* #undef JEMALLOC_IVSALLOC */ + +/* + * Define overrides for non-standard allocator-related functions if they + * are present on the system. + */ +#define JEMALLOC_OVERRIDE_MEMALIGN +#define JEMALLOC_OVERRIDE_VALLOC + +/* + * At least Linux omits the "const" in: + * + * size_t malloc_usable_size(const void *ptr); + * + * Match the operating system's prototype. + */ +#define JEMALLOC_USABLE_SIZE_CONST + +/* + * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. + */ +/* #undef JEMALLOC_ZONE */ +/* #undef JEMALLOC_ZONE_VERSION */ + +/* + * Methods for purging unused pages differ between operating systems. + * + * madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages, + * such that new pages will be demand-zeroed if + * the address region is later touched. + * madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being + * unused, such that they will be discarded rather + * than swapped out. + */ +#define JEMALLOC_PURGE_MADVISE_DONTNEED +/* #undef JEMALLOC_PURGE_MADVISE_FREE */ + +/* + * Define if operating system has alloca.h header. + */ +#define JEMALLOC_HAS_ALLOCA_H + +/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#define LG_SIZEOF_PTR @JEM_SIZEDEF@ + +/* sizeof(int) == 2^LG_SIZEOF_INT. */ +#define LG_SIZEOF_INT 2 + +/* sizeof(long) == 2^LG_SIZEOF_LONG. */ +#define LG_SIZEOF_LONG @JEM_SIZEDEF@ + +/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */ +#define LG_SIZEOF_INTMAX_T 3 diff --git a/dep/jemalloc/src/arena.c b/dep/jemalloc/src/arena.c index 7f939b3cd77..05a787f89d9 100644 --- a/dep/jemalloc/src/arena.c +++ b/dep/jemalloc/src/arena.c @@ -4,176 +4,71 @@ /******************************************************************************/ /* Data. */ -size_t opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT; -size_t opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT; ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; -uint8_t const *small_size2bin; - -/* Various bin-related settings. */ -unsigned nqbins; -unsigned ncbins; -unsigned nsbins; -unsigned nbins; -size_t qspace_max; -size_t cspace_min; -size_t cspace_max; -size_t sspace_min; -size_t sspace_max; - -size_t lg_mspace; -size_t mspace_mask; +arena_bin_info_t arena_bin_info[NBINS]; -/* - * const_small_size2bin is a static constant lookup table that in the common - * case can be used as-is for small_size2bin. For dynamically linked programs, - * this avoids a page of memory overhead per process. - */ -#define S2B_1(i) i, -#define S2B_2(i) S2B_1(i) S2B_1(i) -#define S2B_4(i) S2B_2(i) S2B_2(i) -#define S2B_8(i) S2B_4(i) S2B_4(i) +JEMALLOC_ALIGNED(CACHELINE) +const uint8_t small_size2bin[] = { +#define S2B_8(i) i, #define S2B_16(i) S2B_8(i) S2B_8(i) #define S2B_32(i) S2B_16(i) S2B_16(i) #define S2B_64(i) S2B_32(i) S2B_32(i) #define S2B_128(i) S2B_64(i) S2B_64(i) #define S2B_256(i) S2B_128(i) S2B_128(i) -/* - * The number of elements in const_small_size2bin is dependent on page size - * and on the definition for SUBPAGE. If SUBPAGE changes, the '- 255' must also - * change, along with the addition/removal of static lookup table element - * definitions. - */ -static const uint8_t const_small_size2bin[STATIC_PAGE_SIZE - 255] = { - S2B_1(0xffU) /* 0 */ -#if (LG_QUANTUM == 4) -/* 16-byte quantum **********************/ -# ifdef JEMALLOC_TINY -# if (LG_TINY_MIN == 2) - S2B_4(0) /* 4 */ - S2B_4(1) /* 8 */ - S2B_8(2) /* 16 */ -# define S2B_QMIN 2 -# elif (LG_TINY_MIN == 3) - S2B_8(0) /* 8 */ - S2B_8(1) /* 16 */ -# define S2B_QMIN 1 -# else -# error "Unsupported LG_TINY_MIN" -# endif -# else - S2B_16(0) /* 16 */ -# define S2B_QMIN 0 -# endif - S2B_16(S2B_QMIN + 1) /* 32 */ - S2B_16(S2B_QMIN + 2) /* 48 */ - S2B_16(S2B_QMIN + 3) /* 64 */ - S2B_16(S2B_QMIN + 4) /* 80 */ - S2B_16(S2B_QMIN + 5) /* 96 */ - S2B_16(S2B_QMIN + 6) /* 112 */ - S2B_16(S2B_QMIN + 7) /* 128 */ -# define S2B_CMIN (S2B_QMIN + 8) -#else -/* 8-byte quantum ***********************/ -# ifdef JEMALLOC_TINY -# if (LG_TINY_MIN == 2) - S2B_4(0) /* 4 */ - S2B_4(1) /* 8 */ -# define S2B_QMIN 1 -# else -# error "Unsupported LG_TINY_MIN" -# endif -# else - S2B_8(0) /* 8 */ -# define S2B_QMIN 0 -# endif - S2B_8(S2B_QMIN + 1) /* 16 */ - S2B_8(S2B_QMIN + 2) /* 24 */ - S2B_8(S2B_QMIN + 3) /* 32 */ - S2B_8(S2B_QMIN + 4) /* 40 */ - S2B_8(S2B_QMIN + 5) /* 48 */ - S2B_8(S2B_QMIN + 6) /* 56 */ - S2B_8(S2B_QMIN + 7) /* 64 */ - S2B_8(S2B_QMIN + 8) /* 72 */ - S2B_8(S2B_QMIN + 9) /* 80 */ - S2B_8(S2B_QMIN + 10) /* 88 */ - S2B_8(S2B_QMIN + 11) /* 96 */ - S2B_8(S2B_QMIN + 12) /* 104 */ - S2B_8(S2B_QMIN + 13) /* 112 */ - S2B_8(S2B_QMIN + 14) /* 120 */ - S2B_8(S2B_QMIN + 15) /* 128 */ -# define S2B_CMIN (S2B_QMIN + 16) -#endif -/****************************************/ - S2B_64(S2B_CMIN + 0) /* 192 */ - S2B_64(S2B_CMIN + 1) /* 256 */ - S2B_64(S2B_CMIN + 2) /* 320 */ - S2B_64(S2B_CMIN + 3) /* 384 */ - S2B_64(S2B_CMIN + 4) /* 448 */ - S2B_64(S2B_CMIN + 5) /* 512 */ -# define S2B_SMIN (S2B_CMIN + 6) - S2B_256(S2B_SMIN + 0) /* 768 */ - S2B_256(S2B_SMIN + 1) /* 1024 */ - S2B_256(S2B_SMIN + 2) /* 1280 */ - S2B_256(S2B_SMIN + 3) /* 1536 */ - S2B_256(S2B_SMIN + 4) /* 1792 */ - S2B_256(S2B_SMIN + 5) /* 2048 */ - S2B_256(S2B_SMIN + 6) /* 2304 */ - S2B_256(S2B_SMIN + 7) /* 2560 */ - S2B_256(S2B_SMIN + 8) /* 2816 */ - S2B_256(S2B_SMIN + 9) /* 3072 */ - S2B_256(S2B_SMIN + 10) /* 3328 */ - S2B_256(S2B_SMIN + 11) /* 3584 */ - S2B_256(S2B_SMIN + 12) /* 3840 */ -#if (STATIC_PAGE_SHIFT == 13) - S2B_256(S2B_SMIN + 13) /* 4096 */ - S2B_256(S2B_SMIN + 14) /* 4352 */ - S2B_256(S2B_SMIN + 15) /* 4608 */ - S2B_256(S2B_SMIN + 16) /* 4864 */ - S2B_256(S2B_SMIN + 17) /* 5120 */ - S2B_256(S2B_SMIN + 18) /* 5376 */ - S2B_256(S2B_SMIN + 19) /* 5632 */ - S2B_256(S2B_SMIN + 20) /* 5888 */ - S2B_256(S2B_SMIN + 21) /* 6144 */ - S2B_256(S2B_SMIN + 22) /* 6400 */ - S2B_256(S2B_SMIN + 23) /* 6656 */ - S2B_256(S2B_SMIN + 24) /* 6912 */ - S2B_256(S2B_SMIN + 25) /* 7168 */ - S2B_256(S2B_SMIN + 26) /* 7424 */ - S2B_256(S2B_SMIN + 27) /* 7680 */ - S2B_256(S2B_SMIN + 28) /* 7936 */ -#endif -}; -#undef S2B_1 -#undef S2B_2 -#undef S2B_4 +#define S2B_512(i) S2B_256(i) S2B_256(i) +#define S2B_1024(i) S2B_512(i) S2B_512(i) +#define S2B_2048(i) S2B_1024(i) S2B_1024(i) +#define S2B_4096(i) S2B_2048(i) S2B_2048(i) +#define S2B_8192(i) S2B_4096(i) S2B_4096(i) +#define SIZE_CLASS(bin, delta, size) \ + S2B_##delta(bin) + SIZE_CLASSES #undef S2B_8 #undef S2B_16 #undef S2B_32 #undef S2B_64 #undef S2B_128 #undef S2B_256 -#undef S2B_QMIN -#undef S2B_CMIN -#undef S2B_SMIN +#undef S2B_512 +#undef S2B_1024 +#undef S2B_2048 +#undef S2B_4096 +#undef S2B_8192 +#undef SIZE_CLASS +}; /******************************************************************************/ /* Function prototypes for non-inline static functions. */ +static void arena_avail_insert(arena_t *arena, arena_chunk_t *chunk, + size_t pageind, size_t npages, bool maybe_adjac_pred, + bool maybe_adjac_succ); +static void arena_avail_remove(arena_t *arena, arena_chunk_t *chunk, + size_t pageind, size_t npages, bool maybe_adjac_pred, + bool maybe_adjac_succ); static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, - bool large, bool zero); + bool large, size_t binind, bool zero); static arena_chunk_t *arena_chunk_alloc(arena_t *arena); static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); +static arena_run_t *arena_run_alloc_helper(arena_t *arena, size_t size, + bool large, size_t binind, bool zero); static arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large, - bool zero); + size_t binind, bool zero); +static arena_chunk_t *chunks_dirty_iter_cb(arena_chunk_tree_t *tree, + arena_chunk_t *chunk, void *arg); static void arena_purge(arena_t *arena, bool all); -static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty); +static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, + bool cleaned); static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, size_t oldsize, size_t newsize); static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, size_t oldsize, size_t newsize, bool dirty); +static arena_run_t *arena_bin_runs_first(arena_bin_t *bin); +static void arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run); +static void arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run); +static arena_run_t *arena_bin_nonfull_run_tryget(arena_bin_t *bin); static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin); static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin); -static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size); static void arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, arena_bin_t *bin); static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, @@ -186,11 +81,9 @@ static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, size_t oldsize, size_t size, size_t extra, bool zero); static bool arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, bool zero); -static bool small_size2bin_init(void); -#ifdef JEMALLOC_DEBUG -static void small_size2bin_validate(void); -#endif -static bool small_size2bin_init_hard(void); +static size_t bin_info_run_size_calc(arena_bin_info_t *bin_info, + size_t min_run_size); +static void bin_info_init(void); /******************************************************************************/ @@ -207,8 +100,8 @@ arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) } /* Generate red-black tree functions. */ -rb_gen(static JEMALLOC_ATTR(unused), arena_run_tree_, arena_run_tree_t, - arena_chunk_map_t, u.rb_link, arena_run_comp) +rb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, + u.rb_link, arena_run_comp) static inline int arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) @@ -217,9 +110,6 @@ arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) size_t a_size = a->bits & ~PAGE_MASK; size_t b_size = b->bits & ~PAGE_MASK; - assert((a->bits & CHUNK_MAP_KEY) == CHUNK_MAP_KEY || (a->bits & - CHUNK_MAP_DIRTY) == (b->bits & CHUNK_MAP_DIRTY)); - ret = (a_size > b_size) - (a_size < b_size); if (ret == 0) { uintptr_t a_mapelm, b_mapelm; @@ -242,129 +132,311 @@ arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) } /* Generate red-black tree functions. */ -rb_gen(static JEMALLOC_ATTR(unused), arena_avail_tree_, arena_avail_tree_t, - arena_chunk_map_t, u.rb_link, arena_avail_comp) +rb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, + u.rb_link, arena_avail_comp) + +static inline int +arena_chunk_dirty_comp(arena_chunk_t *a, arena_chunk_t *b) +{ + + assert(a != NULL); + assert(b != NULL); + + /* + * Short-circuit for self comparison. The following comparison code + * would come to the same result, but at the cost of executing the slow + * path. + */ + if (a == b) + return (0); + + /* + * Order such that chunks with higher fragmentation are "less than" + * those with lower fragmentation -- purging order is from "least" to + * "greatest". Fragmentation is measured as: + * + * mean current avail run size + * -------------------------------- + * mean defragmented avail run size + * + * navail + * ----------- + * nruns_avail nruns_avail-nruns_adjac + * = ========================= = ----------------------- + * navail nruns_avail + * ----------------------- + * nruns_avail-nruns_adjac + * + * The following code multiplies away the denominator prior to + * comparison, in order to avoid division. + * + */ + { + size_t a_val = (a->nruns_avail - a->nruns_adjac) * + b->nruns_avail; + size_t b_val = (b->nruns_avail - b->nruns_adjac) * + a->nruns_avail; + + if (a_val < b_val) + return (1); + if (a_val > b_val) + return (-1); + } + /* + * Break ties by chunk address. For fragmented chunks, report lower + * addresses as "lower", so that fragmentation reduction happens first + * at lower addresses. However, use the opposite ordering for + * unfragmented chunks, in order to increase the chances of + * re-allocating dirty runs. + */ + { + uintptr_t a_chunk = (uintptr_t)a; + uintptr_t b_chunk = (uintptr_t)b; + int ret = ((a_chunk > b_chunk) - (a_chunk < b_chunk)); + if (a->nruns_adjac == 0) { + assert(b->nruns_adjac == 0); + ret = -ret; + } + return (ret); + } +} + +/* Generate red-black tree functions. */ +rb_gen(static UNUSED, arena_chunk_dirty_, arena_chunk_tree_t, arena_chunk_t, + dirty_link, arena_chunk_dirty_comp) + +static inline bool +arena_avail_adjac_pred(arena_chunk_t *chunk, size_t pageind) +{ + bool ret; + + if (pageind-1 < map_bias) + ret = false; + else { + ret = (arena_mapbits_allocated_get(chunk, pageind-1) == 0); + assert(ret == false || arena_mapbits_dirty_get(chunk, + pageind-1) != arena_mapbits_dirty_get(chunk, pageind)); + } + return (ret); +} + +static inline bool +arena_avail_adjac_succ(arena_chunk_t *chunk, size_t pageind, size_t npages) +{ + bool ret; + + if (pageind+npages == chunk_npages) + ret = false; + else { + assert(pageind+npages < chunk_npages); + ret = (arena_mapbits_allocated_get(chunk, pageind+npages) == 0); + assert(ret == false || arena_mapbits_dirty_get(chunk, pageind) + != arena_mapbits_dirty_get(chunk, pageind+npages)); + } + return (ret); +} + +static inline bool +arena_avail_adjac(arena_chunk_t *chunk, size_t pageind, size_t npages) +{ + + return (arena_avail_adjac_pred(chunk, pageind) || + arena_avail_adjac_succ(chunk, pageind, npages)); +} + +static void +arena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind, + size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ) +{ + + assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >> + LG_PAGE)); + + /* + * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be + * removed and reinserted even if the run to be inserted is clean. + */ + if (chunk->ndirty != 0) + arena_chunk_dirty_remove(&arena->chunks_dirty, chunk); + + if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind)) + chunk->nruns_adjac++; + if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages)) + chunk->nruns_adjac++; + chunk->nruns_avail++; + assert(chunk->nruns_avail > chunk->nruns_adjac); + + if (arena_mapbits_dirty_get(chunk, pageind) != 0) { + arena->ndirty += npages; + chunk->ndirty += npages; + } + if (chunk->ndirty != 0) + arena_chunk_dirty_insert(&arena->chunks_dirty, chunk); + + arena_avail_tree_insert(&arena->runs_avail, arena_mapp_get(chunk, + pageind)); +} + +static void +arena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind, + size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ) +{ + + assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >> + LG_PAGE)); + + /* + * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be + * removed and reinserted even if the run to be removed is clean. + */ + if (chunk->ndirty != 0) + arena_chunk_dirty_remove(&arena->chunks_dirty, chunk); + + if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind)) + chunk->nruns_adjac--; + if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages)) + chunk->nruns_adjac--; + chunk->nruns_avail--; + assert(chunk->nruns_avail > chunk->nruns_adjac || (chunk->nruns_avail + == 0 && chunk->nruns_adjac == 0)); + + if (arena_mapbits_dirty_get(chunk, pageind) != 0) { + arena->ndirty -= npages; + chunk->ndirty -= npages; + } + if (chunk->ndirty != 0) + arena_chunk_dirty_insert(&arena->chunks_dirty, chunk); + + arena_avail_tree_remove(&arena->runs_avail, arena_mapp_get(chunk, + pageind)); +} static inline void * -arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin) +arena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info) { void *ret; + unsigned regind; + bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + + (uintptr_t)bin_info->bitmap_offset); - assert(run->magic == ARENA_RUN_MAGIC); assert(run->nfree > 0); + assert(bitmap_full(bitmap, &bin_info->bitmap_info) == false); + regind = bitmap_sfu(bitmap, &bin_info->bitmap_info); + ret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset + + (uintptr_t)(bin_info->reg_interval * regind)); run->nfree--; - ret = run->avail; - if (ret != NULL) { - /* Double free can cause assertion failure.*/ - assert(ret != NULL); - /* Write-after free can cause assertion failure. */ - assert((uintptr_t)ret >= (uintptr_t)run + - (uintptr_t)bin->reg0_offset); - assert((uintptr_t)ret < (uintptr_t)run->next); - assert(((uintptr_t)ret - ((uintptr_t)run + - (uintptr_t)bin->reg0_offset)) % (uintptr_t)bin->reg_size == - 0); - run->avail = *(void **)ret; - return (ret); - } - ret = run->next; - run->next = (void *)((uintptr_t)ret + (uintptr_t)bin->reg_size); - assert(ret != NULL); + if (regind == run->nextind) + run->nextind++; + assert(regind < run->nextind); return (ret); } static inline void arena_run_reg_dalloc(arena_run_t *run, void *ptr) { - - assert(run->nfree < run->bin->nregs); + arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); + size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + size_t mapbits = arena_mapbits_get(chunk, pageind); + size_t binind = arena_ptr_small_binind_get(ptr, mapbits); + arena_bin_info_t *bin_info = &arena_bin_info[binind]; + unsigned regind = arena_run_regind(run, bin_info, ptr); + bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + + (uintptr_t)bin_info->bitmap_offset); + + assert(run->nfree < bin_info->nregs); /* Freeing an interior pointer can cause assertion failure. */ assert(((uintptr_t)ptr - ((uintptr_t)run + - (uintptr_t)run->bin->reg0_offset)) % (uintptr_t)run->bin->reg_size - == 0); - /* - * Freeing a pointer lower than region zero can cause assertion - * failure. - */ + (uintptr_t)bin_info->reg0_offset)) % + (uintptr_t)bin_info->reg_interval == 0); assert((uintptr_t)ptr >= (uintptr_t)run + - (uintptr_t)run->bin->reg0_offset); - /* - * Freeing a pointer past in the run's frontier can cause assertion - * failure. - */ - assert((uintptr_t)ptr < (uintptr_t)run->next); + (uintptr_t)bin_info->reg0_offset); + /* Freeing an unallocated pointer can cause assertion failure. */ + assert(bitmap_get(bitmap, &bin_info->bitmap_info, regind)); - *(void **)ptr = run->avail; - run->avail = ptr; + bitmap_unset(bitmap, &bin_info->bitmap_info, regind); run->nfree++; } -#ifdef JEMALLOC_DEBUG static inline void -arena_chunk_validate_zeroed(arena_chunk_t *chunk, size_t run_ind) +arena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages) +{ + + VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << + LG_PAGE)), (npages << LG_PAGE)); + memset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0, + (npages << LG_PAGE)); +} + +static inline void +arena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind) { size_t i; - size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << PAGE_SHIFT)); + UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE)); - for (i = 0; i < PAGE_SIZE / sizeof(size_t); i++) + VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind << + LG_PAGE)), PAGE); + for (i = 0; i < PAGE / sizeof(size_t); i++) assert(p[i] == 0); } -#endif static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, - bool zero) + size_t binind, bool zero) { arena_chunk_t *chunk; - size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i; + size_t run_ind, total_pages, need_pages, rem_pages, i; size_t flag_dirty; - arena_avail_tree_t *runs_avail; + + assert((large && binind == BININD_INVALID) || (large == false && binind + != BININD_INVALID)); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - old_ndirty = chunk->ndirty; - run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) - >> PAGE_SHIFT); - flag_dirty = chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY; - runs_avail = (flag_dirty != 0) ? &arena->runs_avail_dirty : - &arena->runs_avail_clean; - total_pages = (chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) >> - PAGE_SHIFT; - assert((chunk->map[run_ind+total_pages-1-map_bias].bits & - CHUNK_MAP_DIRTY) == flag_dirty); - need_pages = (size >> PAGE_SHIFT); + run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); + flag_dirty = arena_mapbits_dirty_get(chunk, run_ind); + total_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >> + LG_PAGE; + assert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) == + flag_dirty); + need_pages = (size >> LG_PAGE); assert(need_pages > 0); assert(need_pages <= total_pages); rem_pages = total_pages - need_pages; - arena_avail_tree_remove(runs_avail, &chunk->map[run_ind-map_bias]); + arena_avail_remove(arena, chunk, run_ind, total_pages, true, true); + if (config_stats) { + /* + * Update stats_cactive if nactive is crossing a chunk + * multiple. + */ + size_t cactive_diff = CHUNK_CEILING((arena->nactive + + need_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive << + LG_PAGE); + if (cactive_diff != 0) + stats_cactive_add(cactive_diff); + } arena->nactive += need_pages; /* Keep track of trailing unused pages for later use. */ if (rem_pages > 0) { if (flag_dirty != 0) { - chunk->map[run_ind+need_pages-map_bias].bits = - (rem_pages << PAGE_SHIFT) | CHUNK_MAP_DIRTY; - chunk->map[run_ind+total_pages-1-map_bias].bits = - (rem_pages << PAGE_SHIFT) | CHUNK_MAP_DIRTY; + arena_mapbits_unallocated_set(chunk, run_ind+need_pages, + (rem_pages << LG_PAGE), CHUNK_MAP_DIRTY); + arena_mapbits_unallocated_set(chunk, + run_ind+total_pages-1, (rem_pages << LG_PAGE), + CHUNK_MAP_DIRTY); } else { - chunk->map[run_ind+need_pages-map_bias].bits = - (rem_pages << PAGE_SHIFT) | - (chunk->map[run_ind+need_pages-map_bias].bits & - CHUNK_MAP_UNZEROED); - chunk->map[run_ind+total_pages-1-map_bias].bits = - (rem_pages << PAGE_SHIFT) | - (chunk->map[run_ind+total_pages-1-map_bias].bits & - CHUNK_MAP_UNZEROED); + arena_mapbits_unallocated_set(chunk, run_ind+need_pages, + (rem_pages << LG_PAGE), + arena_mapbits_unzeroed_get(chunk, + run_ind+need_pages)); + arena_mapbits_unallocated_set(chunk, + run_ind+total_pages-1, (rem_pages << LG_PAGE), + arena_mapbits_unzeroed_get(chunk, + run_ind+total_pages-1)); } - arena_avail_tree_insert(runs_avail, - &chunk->map[run_ind+need_pages-map_bias]); - } - - /* Update dirty page accounting. */ - if (flag_dirty != 0) { - chunk->ndirty -= need_pages; - arena->ndirty -= need_pages; + arena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages, + false, true); } /* @@ -379,28 +451,21 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, * zeroed (i.e. never before touched). */ for (i = 0; i < need_pages; i++) { - if ((chunk->map[run_ind+i-map_bias].bits - & CHUNK_MAP_UNZEROED) != 0) { - memset((void *)((uintptr_t) - chunk + ((run_ind+i) << - PAGE_SHIFT)), 0, - PAGE_SIZE); - } -#ifdef JEMALLOC_DEBUG - else { - arena_chunk_validate_zeroed( + if (arena_mapbits_unzeroed_get(chunk, + run_ind+i) != 0) { + arena_run_zero(chunk, run_ind+i, + 1); + } else if (config_debug) { + arena_run_page_validate_zeroed( chunk, run_ind+i); } -#endif } } else { /* * The run is dirty, so all pages must be * zeroed. */ - memset((void *)((uintptr_t)chunk + (run_ind << - PAGE_SHIFT)), 0, (need_pages << - PAGE_SHIFT)); + arena_run_zero(chunk, run_ind, need_pages); } } @@ -408,10 +473,9 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, * Set the last element first, in case the run only contains one * page (i.e. both statements set the same element). */ - chunk->map[run_ind+need_pages-1-map_bias].bits = - CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED | flag_dirty; - chunk->map[run_ind-map_bias].bits = size | flag_dirty | - CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; + arena_mapbits_large_set(chunk, run_ind+need_pages-1, 0, + flag_dirty); + arena_mapbits_large_set(chunk, run_ind, size, flag_dirty); } else { assert(zero == false); /* @@ -419,44 +483,34 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, * small run, so that arena_dalloc_bin_run() has the ability to * conditionally trim clean pages. */ - chunk->map[run_ind-map_bias].bits = - (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED) | - CHUNK_MAP_ALLOCATED | flag_dirty; -#ifdef JEMALLOC_DEBUG + arena_mapbits_small_set(chunk, run_ind, 0, binind, flag_dirty); /* * The first page will always be dirtied during small run * initialization, so a validation failure here would not * actually cause an observable failure. */ - if (flag_dirty == 0 && - (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED) - == 0) - arena_chunk_validate_zeroed(chunk, run_ind); -#endif + if (config_debug && flag_dirty == 0 && + arena_mapbits_unzeroed_get(chunk, run_ind) == 0) + arena_run_page_validate_zeroed(chunk, run_ind); for (i = 1; i < need_pages - 1; i++) { - chunk->map[run_ind+i-map_bias].bits = (i << PAGE_SHIFT) - | (chunk->map[run_ind+i-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED; -#ifdef JEMALLOC_DEBUG - if (flag_dirty == 0 && - (chunk->map[run_ind+i-map_bias].bits & - CHUNK_MAP_UNZEROED) == 0) - arena_chunk_validate_zeroed(chunk, run_ind+i); -#endif + arena_mapbits_small_set(chunk, run_ind+i, i, binind, 0); + if (config_debug && flag_dirty == 0 && + arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0) { + arena_run_page_validate_zeroed(chunk, + run_ind+i); + } } - chunk->map[run_ind+need_pages-1-map_bias].bits = ((need_pages - - 1) << PAGE_SHIFT) | - (chunk->map[run_ind+need_pages-1-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED | flag_dirty; -#ifdef JEMALLOC_DEBUG - if (flag_dirty == 0 && - (chunk->map[run_ind+need_pages-1-map_bias].bits & - CHUNK_MAP_UNZEROED) == 0) { - arena_chunk_validate_zeroed(chunk, + arena_mapbits_small_set(chunk, run_ind+need_pages-1, + need_pages-1, binind, flag_dirty); + if (config_debug && flag_dirty == 0 && + arena_mapbits_unzeroed_get(chunk, run_ind+need_pages-1) == + 0) { + arena_run_page_validate_zeroed(chunk, run_ind+need_pages-1); } -#endif } + VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << + LG_PAGE)), (need_pages << LG_PAGE)); } static arena_chunk_t * @@ -466,40 +520,32 @@ arena_chunk_alloc(arena_t *arena) size_t i; if (arena->spare != NULL) { - arena_avail_tree_t *runs_avail; - chunk = arena->spare; arena->spare = NULL; - /* Insert the run into the appropriate runs_avail_* tree. */ - if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0) - runs_avail = &arena->runs_avail_clean; - else - runs_avail = &arena->runs_avail_dirty; - assert((chunk->map[0].bits & ~PAGE_MASK) == arena_maxclass); - assert((chunk->map[chunk_npages-1-map_bias].bits & ~PAGE_MASK) - == arena_maxclass); - assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) == - (chunk->map[chunk_npages-1-map_bias].bits & - CHUNK_MAP_DIRTY)); - arena_avail_tree_insert(runs_avail, &chunk->map[0]); + assert(arena_mapbits_allocated_get(chunk, map_bias) == 0); + assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0); + assert(arena_mapbits_unallocated_size_get(chunk, map_bias) == + arena_maxclass); + assert(arena_mapbits_unallocated_size_get(chunk, + chunk_npages-1) == arena_maxclass); + assert(arena_mapbits_dirty_get(chunk, map_bias) == + arena_mapbits_dirty_get(chunk, chunk_npages-1)); } else { bool zero; size_t unzeroed; zero = false; malloc_mutex_unlock(&arena->lock); - chunk = (arena_chunk_t *)chunk_alloc(chunksize, false, &zero); + chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize, + false, &zero, arena->dss_prec); malloc_mutex_lock(&arena->lock); if (chunk == NULL) return (NULL); -#ifdef JEMALLOC_STATS - arena->stats.mapped += chunksize; -#endif + if (config_stats) + arena->stats.mapped += chunksize; chunk->arena = arena; - ql_elm_new(chunk, link_dirty); - chunk->dirtied = false; /* * Claim that no pages are in use, since the header is merely @@ -507,85 +553,87 @@ arena_chunk_alloc(arena_t *arena) */ chunk->ndirty = 0; + chunk->nruns_avail = 0; + chunk->nruns_adjac = 0; + /* * Initialize the map to contain one maximal free untouched run. * Mark the pages as zeroed iff chunk_alloc() returned a zeroed * chunk. */ unzeroed = zero ? 0 : CHUNK_MAP_UNZEROED; - chunk->map[0].bits = arena_maxclass | unzeroed; + arena_mapbits_unallocated_set(chunk, map_bias, arena_maxclass, + unzeroed); /* * There is no need to initialize the internal page map entries * unless the chunk is not zeroed. */ if (zero == false) { for (i = map_bias+1; i < chunk_npages-1; i++) - chunk->map[i-map_bias].bits = unzeroed; - } -#ifdef JEMALLOC_DEBUG - else { - for (i = map_bias+1; i < chunk_npages-1; i++) - assert(chunk->map[i-map_bias].bits == unzeroed); + arena_mapbits_unzeroed_set(chunk, i, unzeroed); + } else if (config_debug) { + VALGRIND_MAKE_MEM_DEFINED( + (void *)arena_mapp_get(chunk, map_bias+1), + (void *)((uintptr_t) + arena_mapp_get(chunk, chunk_npages-1) + - (uintptr_t)arena_mapp_get(chunk, map_bias+1))); + for (i = map_bias+1; i < chunk_npages-1; i++) { + assert(arena_mapbits_unzeroed_get(chunk, i) == + unzeroed); + } } -#endif - chunk->map[chunk_npages-1-map_bias].bits = arena_maxclass | - unzeroed; - - /* Insert the run into the runs_avail_clean tree. */ - arena_avail_tree_insert(&arena->runs_avail_clean, - &chunk->map[0]); + arena_mapbits_unallocated_set(chunk, chunk_npages-1, + arena_maxclass, unzeroed); } + /* Insert the run into the runs_avail tree. */ + arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias, + false, false); + return (chunk); } static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) { - arena_avail_tree_t *runs_avail; + assert(arena_mapbits_allocated_get(chunk, map_bias) == 0); + assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0); + assert(arena_mapbits_unallocated_size_get(chunk, map_bias) == + arena_maxclass); + assert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) == + arena_maxclass); + assert(arena_mapbits_dirty_get(chunk, map_bias) == + arena_mapbits_dirty_get(chunk, chunk_npages-1)); /* - * Remove run from the appropriate runs_avail_* tree, so that the arena - * does not use it. + * Remove run from the runs_avail tree, so that the arena does not use + * it. */ - if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0) - runs_avail = &arena->runs_avail_clean; - else - runs_avail = &arena->runs_avail_dirty; - arena_avail_tree_remove(runs_avail, &chunk->map[0]); + arena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias, + false, false); if (arena->spare != NULL) { arena_chunk_t *spare = arena->spare; arena->spare = chunk; - if (spare->dirtied) { - ql_remove(&chunk->arena->chunks_dirty, spare, - link_dirty); - arena->ndirty -= spare->ndirty; - } malloc_mutex_unlock(&arena->lock); - chunk_dealloc((void *)spare, chunksize); + chunk_dealloc((void *)spare, chunksize, true); malloc_mutex_lock(&arena->lock); -#ifdef JEMALLOC_STATS - arena->stats.mapped -= chunksize; -#endif + if (config_stats) + arena->stats.mapped -= chunksize; } else arena->spare = chunk; } static arena_run_t * -arena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) +arena_run_alloc_helper(arena_t *arena, size_t size, bool large, size_t binind, + bool zero) { - arena_chunk_t *chunk; arena_run_t *run; arena_chunk_map_t *mapelm, key; - assert(size <= arena_maxclass); - assert((size & PAGE_MASK) == 0); - - /* Search the arena's chunks for the lowest best fit. */ key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key); + mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); if (mapelm != NULL) { arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); size_t pageind = (((uintptr_t)mapelm - @@ -593,31 +641,38 @@ arena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) + map_bias; run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); + LG_PAGE)); + arena_run_split(arena, run, size, large, binind, zero); return (run); } - mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); + return (NULL); +} + +static arena_run_t * +arena_run_alloc(arena_t *arena, size_t size, bool large, size_t binind, + bool zero) +{ + arena_chunk_t *chunk; + arena_run_t *run; + + assert(size <= arena_maxclass); + assert((size & PAGE_MASK) == 0); + assert((large && binind == BININD_INVALID) || (large == false && binind + != BININD_INVALID)); + + /* Search the arena's chunks for the lowest best fit. */ + run = arena_run_alloc_helper(arena, size, large, binind, zero); + if (run != NULL) return (run); - } /* * No usable runs. Create a new chunk from which to allocate the run. */ chunk = arena_chunk_alloc(arena); if (chunk != NULL) { - run = (arena_run_t *)((uintptr_t)chunk + (map_bias << - PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); + run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE)); + arena_run_split(arena, run, size, large, binind, zero); return (run); } @@ -626,78 +681,46 @@ arena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) * sufficient memory available while this one dropped arena->lock in * arena_chunk_alloc(), so search one more time. */ - mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; - - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); - return (run); - } - mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; - - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); - return (run); - } - - return (NULL); + return (arena_run_alloc_helper(arena, size, large, binind, zero)); } static inline void arena_maybe_purge(arena_t *arena) { + size_t npurgeable, threshold; + + /* Don't purge if the option is disabled. */ + if (opt_lg_dirty_mult < 0) + return; + /* Don't purge if all dirty pages are already being purged. */ + if (arena->ndirty <= arena->npurgatory) + return; + npurgeable = arena->ndirty - arena->npurgatory; + threshold = (arena->nactive >> opt_lg_dirty_mult); + /* + * Don't purge unless the number of purgeable pages exceeds the + * threshold. + */ + if (npurgeable <= threshold) + return; - /* Enforce opt_lg_dirty_mult. */ - if (opt_lg_dirty_mult >= 0 && arena->ndirty > arena->npurgatory && - (arena->ndirty - arena->npurgatory) > chunk_npages && - (arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - - arena->npurgatory)) - arena_purge(arena, false); + arena_purge(arena, false); } -static inline void -arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk) +static inline size_t +arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk, bool all) { + size_t npurged; ql_head(arena_chunk_map_t) mapelms; arena_chunk_map_t *mapelm; - size_t pageind, flag_unzeroed; -#ifdef JEMALLOC_DEBUG - size_t ndirty; -#endif -#ifdef JEMALLOC_STATS + size_t pageind, npages; size_t nmadvise; -#endif ql_new(&mapelms); - flag_unzeroed = -#ifdef JEMALLOC_PURGE_MADVISE_DONTNEED - /* - * madvise(..., MADV_DONTNEED) results in zero-filled pages for anonymous - * mappings, but not for file-backed mappings. - */ -# ifdef JEMALLOC_SWAP - swap_enabled ? CHUNK_MAP_UNZEROED : -# endif - 0; -#else - CHUNK_MAP_UNZEROED; -#endif - /* * If chunk is the spare, temporarily re-allocate it, 1) so that its - * run is reinserted into runs_avail_dirty, and 2) so that it cannot be + * run is reinserted into runs_avail, and 2) so that it cannot be * completely discarded by another thread while arena->lock is dropped * by this thread. Note that the arena_run_dalloc() call will * implicitly deallocate the chunk, so no explicit action is required @@ -711,124 +734,135 @@ arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk) * run. */ if (chunk == arena->spare) { - assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) != 0); + assert(arena_mapbits_dirty_get(chunk, map_bias) != 0); + assert(arena_mapbits_dirty_get(chunk, chunk_npages-1) != 0); + arena_chunk_alloc(arena); } - /* Temporarily allocate all free dirty runs within chunk. */ - for (pageind = map_bias; pageind < chunk_npages;) { - mapelm = &chunk->map[pageind-map_bias]; - if ((mapelm->bits & CHUNK_MAP_ALLOCATED) == 0) { - size_t npages; + if (config_stats) + arena->stats.purged += chunk->ndirty; - npages = mapelm->bits >> PAGE_SHIFT; - assert(pageind + npages <= chunk_npages); - if (mapelm->bits & CHUNK_MAP_DIRTY) { - size_t i; + /* + * Operate on all dirty runs if there is no clean/dirty run + * fragmentation. + */ + if (chunk->nruns_adjac == 0) + all = true; - arena_avail_tree_remove( - &arena->runs_avail_dirty, mapelm); + /* + * Temporarily allocate free dirty runs within chunk. If all is false, + * only operate on dirty runs that are fragments; otherwise operate on + * all dirty runs. + */ + for (pageind = map_bias; pageind < chunk_npages; pageind += npages) { + mapelm = arena_mapp_get(chunk, pageind); + if (arena_mapbits_allocated_get(chunk, pageind) == 0) { + size_t run_size = + arena_mapbits_unallocated_size_get(chunk, pageind); - mapelm->bits = (npages << PAGE_SHIFT) | - flag_unzeroed | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - /* - * Update internal elements in the page map, so - * that CHUNK_MAP_UNZEROED is properly set. - */ - for (i = 1; i < npages - 1; i++) { - chunk->map[pageind+i-map_bias].bits = - flag_unzeroed; - } - if (npages > 1) { - chunk->map[ - pageind+npages-1-map_bias].bits = - flag_unzeroed | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - } + npages = run_size >> LG_PAGE; + assert(pageind + npages <= chunk_npages); + assert(arena_mapbits_dirty_get(chunk, pageind) == + arena_mapbits_dirty_get(chunk, pageind+npages-1)); - arena->nactive += npages; + if (arena_mapbits_dirty_get(chunk, pageind) != 0 && + (all || arena_avail_adjac(chunk, pageind, + npages))) { + arena_run_t *run = (arena_run_t *)((uintptr_t) + chunk + (uintptr_t)(pageind << LG_PAGE)); + + arena_run_split(arena, run, run_size, true, + BININD_INVALID, false); /* Append to list for later processing. */ ql_elm_new(mapelm, u.ql_link); ql_tail_insert(&mapelms, mapelm, u.ql_link); } - - pageind += npages; } else { - /* Skip allocated run. */ - if (mapelm->bits & CHUNK_MAP_LARGE) - pageind += mapelm->bits >> PAGE_SHIFT; - else { + /* Skip run. */ + if (arena_mapbits_large_get(chunk, pageind) != 0) { + npages = arena_mapbits_large_size_get(chunk, + pageind) >> LG_PAGE; + } else { + size_t binind; + arena_bin_info_t *bin_info; arena_run_t *run = (arena_run_t *)((uintptr_t) - chunk + (uintptr_t)(pageind << PAGE_SHIFT)); + chunk + (uintptr_t)(pageind << LG_PAGE)); - assert((mapelm->bits >> PAGE_SHIFT) == 0); - assert(run->magic == ARENA_RUN_MAGIC); - pageind += run->bin->run_size >> PAGE_SHIFT; + assert(arena_mapbits_small_runind_get(chunk, + pageind) == 0); + binind = arena_bin_index(arena, run->bin); + bin_info = &arena_bin_info[binind]; + npages = bin_info->run_size >> LG_PAGE; } } } assert(pageind == chunk_npages); - -#ifdef JEMALLOC_DEBUG - ndirty = chunk->ndirty; -#endif -#ifdef JEMALLOC_STATS - arena->stats.purged += chunk->ndirty; -#endif - arena->ndirty -= chunk->ndirty; - chunk->ndirty = 0; - ql_remove(&arena->chunks_dirty, chunk, link_dirty); - chunk->dirtied = false; + assert(chunk->ndirty == 0 || all == false); + assert(chunk->nruns_adjac == 0); malloc_mutex_unlock(&arena->lock); -#ifdef JEMALLOC_STATS - nmadvise = 0; -#endif + if (config_stats) + nmadvise = 0; + npurged = 0; ql_foreach(mapelm, &mapelms, u.ql_link) { - size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; - size_t npages = mapelm->bits >> PAGE_SHIFT; + bool unzeroed; + size_t flag_unzeroed, i; + pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / + sizeof(arena_chunk_map_t)) + map_bias; + npages = arena_mapbits_large_size_get(chunk, pageind) >> + LG_PAGE; assert(pageind + npages <= chunk_npages); -#ifdef JEMALLOC_DEBUG - assert(ndirty >= npages); - ndirty -= npages; -#endif - -#ifdef JEMALLOC_PURGE_MADVISE_DONTNEED - madvise((void *)((uintptr_t)chunk + (pageind << PAGE_SHIFT)), - (npages << PAGE_SHIFT), MADV_DONTNEED); -#elif defined(JEMALLOC_PURGE_MADVISE_FREE) - madvise((void *)((uintptr_t)chunk + (pageind << PAGE_SHIFT)), - (npages << PAGE_SHIFT), MADV_FREE); -#else -# error "No method defined for purging unused dirty pages." -#endif - -#ifdef JEMALLOC_STATS - nmadvise++; -#endif - } -#ifdef JEMALLOC_DEBUG - assert(ndirty == 0); -#endif + unzeroed = pages_purge((void *)((uintptr_t)chunk + (pageind << + LG_PAGE)), (npages << LG_PAGE)); + flag_unzeroed = unzeroed ? CHUNK_MAP_UNZEROED : 0; + /* + * Set the unzeroed flag for all pages, now that pages_purge() + * has returned whether the pages were zeroed as a side effect + * of purging. This chunk map modification is safe even though + * the arena mutex isn't currently owned by this thread, + * because the run is marked as allocated, thus protecting it + * from being modified by any other thread. As long as these + * writes don't perturb the first and last elements' + * CHUNK_MAP_ALLOCATED bits, behavior is well defined. + */ + for (i = 0; i < npages; i++) { + arena_mapbits_unzeroed_set(chunk, pageind+i, + flag_unzeroed); + } + npurged += npages; + if (config_stats) + nmadvise++; + } malloc_mutex_lock(&arena->lock); -#ifdef JEMALLOC_STATS - arena->stats.nmadvise += nmadvise; -#endif + if (config_stats) + arena->stats.nmadvise += nmadvise; /* Deallocate runs. */ for (mapelm = ql_first(&mapelms); mapelm != NULL; mapelm = ql_first(&mapelms)) { - size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)(pageind << PAGE_SHIFT)); + arena_run_t *run; + pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / + sizeof(arena_chunk_map_t)) + map_bias; + run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)(pageind << + LG_PAGE)); ql_remove(&mapelms, mapelm, u.ql_link); - arena_run_dalloc(arena, run, false); + arena_run_dalloc(arena, run, false, true); } + + return (npurged); +} + +static arena_chunk_t * +chunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg) +{ + size_t *ndirty = (size_t *)arg; + + assert(chunk->ndirty != 0); + *ndirty += chunk->ndirty; + return (NULL); } static void @@ -836,36 +870,43 @@ arena_purge(arena_t *arena, bool all) { arena_chunk_t *chunk; size_t npurgatory; -#ifdef JEMALLOC_DEBUG - size_t ndirty = 0; + if (config_debug) { + size_t ndirty = 0; - ql_foreach(chunk, &arena->chunks_dirty, link_dirty) { - assert(chunk->dirtied); - ndirty += chunk->ndirty; + arena_chunk_dirty_iter(&arena->chunks_dirty, NULL, + chunks_dirty_iter_cb, (void *)&ndirty); + assert(ndirty == arena->ndirty); } - assert(ndirty == arena->ndirty); -#endif - assert(arena->ndirty > arena->npurgatory); - assert(arena->ndirty > chunk_npages || all); - assert((arena->nactive >> opt_lg_dirty_mult) < arena->ndirty || all); + assert(arena->ndirty > arena->npurgatory || all); + assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - + arena->npurgatory) || all); -#ifdef JEMALLOC_STATS - arena->stats.npurge++; -#endif + if (config_stats) + arena->stats.npurge++; /* * Compute the minimum number of pages that this thread should try to * purge, and add the result to arena->npurgatory. This will keep * multiple threads from racing to reduce ndirty below the threshold. */ - npurgatory = arena->ndirty - arena->npurgatory; - if (all == false) - npurgatory -= arena->nactive >> opt_lg_dirty_mult; + { + size_t npurgeable = arena->ndirty - arena->npurgatory; + + if (all == false) { + size_t threshold = (arena->nactive >> + opt_lg_dirty_mult); + + npurgatory = npurgeable - threshold; + } else + npurgatory = npurgeable; + } arena->npurgatory += npurgatory; while (npurgatory > 0) { + size_t npurgeable, npurged, nunpurged; + /* Get next chunk with dirty pages. */ - chunk = ql_first(&arena->chunks_dirty); + chunk = arena_chunk_dirty_first(&arena->chunks_dirty); if (chunk == NULL) { /* * This thread was unable to purge as many pages as @@ -876,23 +917,15 @@ arena_purge(arena_t *arena, bool all) arena->npurgatory -= npurgatory; return; } - while (chunk->ndirty == 0) { - ql_remove(&arena->chunks_dirty, chunk, link_dirty); - chunk->dirtied = false; - chunk = ql_first(&arena->chunks_dirty); - if (chunk == NULL) { - /* Same logic as for above. */ - arena->npurgatory -= npurgatory; - return; - } - } + npurgeable = chunk->ndirty; + assert(npurgeable != 0); - if (chunk->ndirty > npurgatory) { + if (npurgeable > npurgatory && chunk->nruns_adjac == 0) { /* - * This thread will, at a minimum, purge all the dirty - * pages in chunk, so set npurgatory to reflect this - * thread's commitment to purge the pages. This tends - * to reduce the chances of the following scenario: + * This thread will purge all the dirty pages in chunk, + * so set npurgatory to reflect this thread's intent to + * purge the pages. This tends to reduce the chances + * of the following scenario: * * 1) This thread sets arena->npurgatory such that * (arena->ndirty - arena->npurgatory) is at the @@ -906,13 +939,20 @@ arena_purge(arena_t *arena, bool all) * because all of the purging work being done really * needs to happen. */ - arena->npurgatory += chunk->ndirty - npurgatory; - npurgatory = chunk->ndirty; + arena->npurgatory += npurgeable - npurgatory; + npurgatory = npurgeable; } - arena->npurgatory -= chunk->ndirty; - npurgatory -= chunk->ndirty; - arena_chunk_purge(arena, chunk); + /* + * Keep track of how many pages are purgeable, versus how many + * actually get purged, and adjust counters accordingly. + */ + arena->npurgatory -= npurgeable; + npurgatory -= npurgeable; + npurged = arena_chunk_purge(arena, chunk, all); + nunpurged = npurgeable - npurged; + arena->npurgatory += nunpurged; + npurgatory += nunpurged; } } @@ -926,96 +966,95 @@ arena_purge_all(arena_t *arena) } static void -arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) +arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned) { arena_chunk_t *chunk; size_t size, run_ind, run_pages, flag_dirty; - arena_avail_tree_t *runs_avail; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) - >> PAGE_SHIFT); + run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); assert(run_ind >= map_bias); assert(run_ind < chunk_npages); - if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_LARGE) != 0) { - size = chunk->map[run_ind-map_bias].bits & ~PAGE_MASK; - assert(size == PAGE_SIZE || - (chunk->map[run_ind+(size>>PAGE_SHIFT)-1-map_bias].bits & - ~PAGE_MASK) == 0); - assert((chunk->map[run_ind+(size>>PAGE_SHIFT)-1-map_bias].bits & - CHUNK_MAP_LARGE) != 0); - assert((chunk->map[run_ind+(size>>PAGE_SHIFT)-1-map_bias].bits & - CHUNK_MAP_ALLOCATED) != 0); - } else - size = run->bin->run_size; - run_pages = (size >> PAGE_SHIFT); + if (arena_mapbits_large_get(chunk, run_ind) != 0) { + size = arena_mapbits_large_size_get(chunk, run_ind); + assert(size == PAGE || + arena_mapbits_large_size_get(chunk, + run_ind+(size>>LG_PAGE)-1) == 0); + } else { + size_t binind = arena_bin_index(arena, run->bin); + arena_bin_info_t *bin_info = &arena_bin_info[binind]; + size = bin_info->run_size; + } + run_pages = (size >> LG_PAGE); + if (config_stats) { + /* + * Update stats_cactive if nactive is crossing a chunk + * multiple. + */ + size_t cactive_diff = CHUNK_CEILING(arena->nactive << LG_PAGE) - + CHUNK_CEILING((arena->nactive - run_pages) << LG_PAGE); + if (cactive_diff != 0) + stats_cactive_sub(cactive_diff); + } arena->nactive -= run_pages; /* * The run is dirty if the caller claims to have dirtied it, as well as - * if it was already dirty before being allocated. + * if it was already dirty before being allocated and the caller + * doesn't claim to have cleaned it. */ - if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) != 0) + assert(arena_mapbits_dirty_get(chunk, run_ind) == + arena_mapbits_dirty_get(chunk, run_ind+run_pages-1)); + if (cleaned == false && arena_mapbits_dirty_get(chunk, run_ind) != 0) dirty = true; flag_dirty = dirty ? CHUNK_MAP_DIRTY : 0; - runs_avail = dirty ? &arena->runs_avail_dirty : - &arena->runs_avail_clean; /* Mark pages as unallocated in the chunk map. */ if (dirty) { - chunk->map[run_ind-map_bias].bits = size | CHUNK_MAP_DIRTY; - chunk->map[run_ind+run_pages-1-map_bias].bits = size | - CHUNK_MAP_DIRTY; - - chunk->ndirty += run_pages; - arena->ndirty += run_pages; + arena_mapbits_unallocated_set(chunk, run_ind, size, + CHUNK_MAP_DIRTY); + arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size, + CHUNK_MAP_DIRTY); } else { - chunk->map[run_ind-map_bias].bits = size | - (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED); - chunk->map[run_ind+run_pages-1-map_bias].bits = size | - (chunk->map[run_ind+run_pages-1-map_bias].bits & - CHUNK_MAP_UNZEROED); + arena_mapbits_unallocated_set(chunk, run_ind, size, + arena_mapbits_unzeroed_get(chunk, run_ind)); + arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size, + arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1)); } /* Try to coalesce forward. */ if (run_ind + run_pages < chunk_npages && - (chunk->map[run_ind+run_pages-map_bias].bits & CHUNK_MAP_ALLOCATED) - == 0 && (chunk->map[run_ind+run_pages-map_bias].bits & - CHUNK_MAP_DIRTY) == flag_dirty) { - size_t nrun_size = chunk->map[run_ind+run_pages-map_bias].bits & - ~PAGE_MASK; - size_t nrun_pages = nrun_size >> PAGE_SHIFT; + arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 && + arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty) { + size_t nrun_size = arena_mapbits_unallocated_size_get(chunk, + run_ind+run_pages); + size_t nrun_pages = nrun_size >> LG_PAGE; /* * Remove successor from runs_avail; the coalesced run is * inserted later. */ - assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits - & ~PAGE_MASK) == nrun_size); - assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits - & CHUNK_MAP_ALLOCATED) == 0); - assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits - & CHUNK_MAP_DIRTY) == flag_dirty); - arena_avail_tree_remove(runs_avail, - &chunk->map[run_ind+run_pages-map_bias]); + assert(arena_mapbits_unallocated_size_get(chunk, + run_ind+run_pages+nrun_pages-1) == nrun_size); + assert(arena_mapbits_dirty_get(chunk, + run_ind+run_pages+nrun_pages-1) == flag_dirty); + arena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages, + false, true); size += nrun_size; run_pages += nrun_pages; - chunk->map[run_ind-map_bias].bits = size | - (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+run_pages-1-map_bias].bits = size | - (chunk->map[run_ind+run_pages-1-map_bias].bits & - CHUNK_MAP_FLAGS_MASK); + arena_mapbits_unallocated_size_set(chunk, run_ind, size); + arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1, + size); } /* Try to coalesce backward. */ - if (run_ind > map_bias && (chunk->map[run_ind-1-map_bias].bits & - CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[run_ind-1-map_bias].bits & - CHUNK_MAP_DIRTY) == flag_dirty) { - size_t prun_size = chunk->map[run_ind-1-map_bias].bits & - ~PAGE_MASK; - size_t prun_pages = prun_size >> PAGE_SHIFT; + if (run_ind > map_bias && arena_mapbits_allocated_get(chunk, run_ind-1) + == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) == flag_dirty) { + size_t prun_size = arena_mapbits_unallocated_size_get(chunk, + run_ind-1); + size_t prun_pages = prun_size >> LG_PAGE; run_ind -= prun_pages; @@ -1023,52 +1062,33 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) * Remove predecessor from runs_avail; the coalesced run is * inserted later. */ - assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) - == prun_size); - assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_ALLOCATED) - == 0); - assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) - == flag_dirty); - arena_avail_tree_remove(runs_avail, - &chunk->map[run_ind-map_bias]); + assert(arena_mapbits_unallocated_size_get(chunk, run_ind) == + prun_size); + assert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty); + arena_avail_remove(arena, chunk, run_ind, prun_pages, true, + false); size += prun_size; run_pages += prun_pages; - chunk->map[run_ind-map_bias].bits = size | - (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+run_pages-1-map_bias].bits = size | - (chunk->map[run_ind+run_pages-1-map_bias].bits & - CHUNK_MAP_FLAGS_MASK); + arena_mapbits_unallocated_size_set(chunk, run_ind, size); + arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1, + size); } /* Insert into runs_avail, now that coalescing is complete. */ - assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) == - (chunk->map[run_ind+run_pages-1-map_bias].bits & ~PAGE_MASK)); - assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) == - (chunk->map[run_ind+run_pages-1-map_bias].bits & CHUNK_MAP_DIRTY)); - arena_avail_tree_insert(runs_avail, &chunk->map[run_ind-map_bias]); - - if (dirty) { - /* - * Insert into chunks_dirty before potentially calling - * arena_chunk_dealloc(), so that chunks_dirty and - * arena->ndirty are consistent. - */ - if (chunk->dirtied == false) { - ql_tail_insert(&arena->chunks_dirty, chunk, link_dirty); - chunk->dirtied = true; - } - } - - /* - * Deallocate chunk if it is now completely unused. The bit - * manipulation checks whether the first run is unallocated and extends - * to the end of the chunk. - */ - if ((chunk->map[0].bits & (~PAGE_MASK | CHUNK_MAP_ALLOCATED)) == - arena_maxclass) + assert(arena_mapbits_unallocated_size_get(chunk, run_ind) == + arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1)); + assert(arena_mapbits_dirty_get(chunk, run_ind) == + arena_mapbits_dirty_get(chunk, run_ind+run_pages-1)); + arena_avail_insert(arena, chunk, run_ind, run_pages, true, true); + + /* Deallocate chunk if it is now completely unused. */ + if (size == arena_maxclass) { + assert(run_ind == map_bias); + assert(run_pages == (arena_maxclass >> LG_PAGE)); arena_chunk_dealloc(arena, chunk); + } /* * It is okay to do dirty page processing here even if the chunk was @@ -1085,9 +1105,9 @@ static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, size_t oldsize, size_t newsize) { - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t head_npages = (oldsize - newsize) >> PAGE_SHIFT; - size_t flag_dirty = chunk->map[pageind-map_bias].bits & CHUNK_MAP_DIRTY; + size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; + size_t head_npages = (oldsize - newsize) >> LG_PAGE; + size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind); assert(oldsize > newsize); @@ -1096,44 +1116,30 @@ arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, * leading run as separately allocated. Set the last element of each * run first, in case of single-page runs. */ - assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0); - assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0); - chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty | - (chunk->map[pageind+head_npages-1-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - chunk->map[pageind-map_bias].bits = (oldsize - newsize) - | flag_dirty | (chunk->map[pageind-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - -#ifdef JEMALLOC_DEBUG - { - size_t tail_npages = newsize >> PAGE_SHIFT; - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] - .bits & ~PAGE_MASK) == 0); - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] - .bits & CHUNK_MAP_DIRTY) == flag_dirty); - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] - .bits & CHUNK_MAP_LARGE) != 0); - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] - .bits & CHUNK_MAP_ALLOCATED) != 0); - } -#endif - chunk->map[pageind+head_npages-map_bias].bits = newsize | flag_dirty | - (chunk->map[pageind+head_npages-map_bias].bits & - CHUNK_MAP_FLAGS_MASK) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - - arena_run_dalloc(arena, run, false); + assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize); + arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty); + arena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty); + + if (config_debug) { + UNUSED size_t tail_npages = newsize >> LG_PAGE; + assert(arena_mapbits_large_size_get(chunk, + pageind+head_npages+tail_npages-1) == 0); + assert(arena_mapbits_dirty_get(chunk, + pageind+head_npages+tail_npages-1) == flag_dirty); + } + arena_mapbits_large_set(chunk, pageind+head_npages, newsize, + flag_dirty); + + arena_run_dalloc(arena, run, false, false); } static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, size_t oldsize, size_t newsize, bool dirty) { - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t head_npages = newsize >> PAGE_SHIFT; - size_t tail_npages = (oldsize - newsize) >> PAGE_SHIFT; - size_t flag_dirty = chunk->map[pageind-map_bias].bits & - CHUNK_MAP_DIRTY; + size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; + size_t head_npages = newsize >> LG_PAGE; + size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind); assert(oldsize > newsize); @@ -1142,87 +1148,120 @@ arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, * trailing run as separately allocated. Set the last element of each * run first, in case of single-page runs. */ - assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0); - assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0); - chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty | - (chunk->map[pageind+head_npages-1-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - chunk->map[pageind-map_bias].bits = newsize | flag_dirty | - (chunk->map[pageind-map_bias].bits & CHUNK_MAP_UNZEROED) | - CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & - ~PAGE_MASK) == 0); - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & - CHUNK_MAP_LARGE) != 0); - assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & - CHUNK_MAP_ALLOCATED) != 0); - chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits = - flag_dirty | - (chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - chunk->map[pageind+head_npages-map_bias].bits = (oldsize - newsize) | - flag_dirty | (chunk->map[pageind+head_npages-map_bias].bits & - CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; + assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize); + arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty); + arena_mapbits_large_set(chunk, pageind, newsize, flag_dirty); + + if (config_debug) { + UNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE; + assert(arena_mapbits_large_size_get(chunk, + pageind+head_npages+tail_npages-1) == 0); + assert(arena_mapbits_dirty_get(chunk, + pageind+head_npages+tail_npages-1) == flag_dirty); + } + arena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize, + flag_dirty); arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), - dirty); + dirty, false); } static arena_run_t * -arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) +arena_bin_runs_first(arena_bin_t *bin) { - arena_chunk_map_t *mapelm; - arena_run_t *run; - - /* Look for a usable run. */ - mapelm = arena_run_tree_first(&bin->runs); + arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs); if (mapelm != NULL) { arena_chunk_t *chunk; size_t pageind; - - /* run is guaranteed to have available space. */ - arena_run_tree_remove(&bin->runs, mapelm); + arena_run_t *run; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / sizeof(arena_chunk_map_t))) + map_bias; run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - (mapelm->bits >> PAGE_SHIFT)) - << PAGE_SHIFT)); -#ifdef JEMALLOC_STATS - bin->stats.reruns++; -#endif + arena_mapbits_small_runind_get(chunk, pageind)) << + LG_PAGE)); return (run); } + + return (NULL); +} + +static void +arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run) +{ + arena_chunk_t *chunk = CHUNK_ADDR2BASE(run); + size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; + arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); + + assert(arena_run_tree_search(&bin->runs, mapelm) == NULL); + + arena_run_tree_insert(&bin->runs, mapelm); +} + +static void +arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run) +{ + arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); + size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; + arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); + + assert(arena_run_tree_search(&bin->runs, mapelm) != NULL); + + arena_run_tree_remove(&bin->runs, mapelm); +} + +static arena_run_t * +arena_bin_nonfull_run_tryget(arena_bin_t *bin) +{ + arena_run_t *run = arena_bin_runs_first(bin); + if (run != NULL) { + arena_bin_runs_remove(bin, run); + if (config_stats) + bin->stats.reruns++; + } + return (run); +} + +static arena_run_t * +arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) +{ + arena_run_t *run; + size_t binind; + arena_bin_info_t *bin_info; + + /* Look for a usable run. */ + run = arena_bin_nonfull_run_tryget(bin); + if (run != NULL) + return (run); /* No existing runs have any space available. */ + binind = arena_bin_index(arena, bin); + bin_info = &arena_bin_info[binind]; + /* Allocate a new run. */ malloc_mutex_unlock(&bin->lock); /******************************/ malloc_mutex_lock(&arena->lock); - run = arena_run_alloc(arena, bin->run_size, false, false); + run = arena_run_alloc(arena, bin_info->run_size, false, binind, false); if (run != NULL) { + bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + + (uintptr_t)bin_info->bitmap_offset); + /* Initialize run internals. */ run->bin = bin; - run->avail = NULL; - run->next = (void *)((uintptr_t)run + - (uintptr_t)bin->reg0_offset); - run->nfree = bin->nregs; -#ifdef JEMALLOC_DEBUG - run->magic = ARENA_RUN_MAGIC; -#endif + run->nextind = 0; + run->nfree = bin_info->nregs; + bitmap_init(bitmap, &bin_info->bitmap_info); } malloc_mutex_unlock(&arena->lock); /********************************/ malloc_mutex_lock(&bin->lock); if (run != NULL) { -#ifdef JEMALLOC_STATS - bin->stats.nruns++; - bin->stats.curruns++; - if (bin->stats.curruns > bin->stats.highruns) - bin->stats.highruns = bin->stats.curruns; -#endif + if (config_stats) { + bin->stats.nruns++; + bin->stats.curruns++; + } return (run); } @@ -1231,25 +1270,9 @@ arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) * sufficient memory available while this one dropped bin->lock above, * so search one more time. */ - mapelm = arena_run_tree_first(&bin->runs); - if (mapelm != NULL) { - arena_chunk_t *chunk; - size_t pageind; - - /* run is guaranteed to have available space. */ - arena_run_tree_remove(&bin->runs, mapelm); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); - pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t))) + map_bias; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - (mapelm->bits >> PAGE_SHIFT)) - << PAGE_SHIFT)); -#ifdef JEMALLOC_STATS - bin->stats.reruns++; -#endif + run = arena_bin_nonfull_run_tryget(bin); + if (run != NULL) return (run); - } return (NULL); } @@ -1259,8 +1282,12 @@ static void * arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) { void *ret; + size_t binind; + arena_bin_info_t *bin_info; arena_run_t *run; + binind = arena_bin_index(arena, bin); + bin_info = &arena_bin_info[binind]; bin->runcur = NULL; run = arena_bin_nonfull_run_get(arena, bin); if (bin->runcur != NULL && bin->runcur->nfree > 0) { @@ -1268,22 +1295,21 @@ arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) * Another thread updated runcur while this one ran without the * bin lock in arena_bin_nonfull_run_get(). */ - assert(bin->runcur->magic == ARENA_RUN_MAGIC); assert(bin->runcur->nfree > 0); - ret = arena_run_reg_alloc(bin->runcur, bin); + ret = arena_run_reg_alloc(bin->runcur, bin_info); if (run != NULL) { arena_chunk_t *chunk; /* * arena_run_alloc() may have allocated run, or it may - * have pulled it from the bin's run tree. Therefore + * have pulled run from the bin's run tree. Therefore * it is unsafe to make any assumptions about how run * has previously been used, and arena_bin_lower_run() * must be called, as if a region were just deallocated * from the run. */ chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - if (run->nfree == bin->nregs) + if (run->nfree == bin_info->nregs) arena_dalloc_bin_run(arena, chunk, run, bin); else arena_bin_lower_run(arena, chunk, run, bin); @@ -1296,34 +1322,14 @@ arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) bin->runcur = run; - assert(bin->runcur->magic == ARENA_RUN_MAGIC); assert(bin->runcur->nfree > 0); - return (arena_run_reg_alloc(bin->runcur, bin)); -} - -#ifdef JEMALLOC_PROF -void -arena_prof_accum(arena_t *arena, uint64_t accumbytes) -{ - - if (prof_interval != 0) { - arena->prof_accumbytes += accumbytes; - if (arena->prof_accumbytes >= prof_interval) { - prof_idump(); - arena->prof_accumbytes -= prof_interval; - } - } + return (arena_run_reg_alloc(bin->runcur, bin_info)); } -#endif -#ifdef JEMALLOC_TCACHE void -arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind -# ifdef JEMALLOC_PROF - , uint64_t prof_accumbytes -# endif - ) +arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind, + uint64_t prof_accumbytes) { unsigned i, nfill; arena_bin_t *bin; @@ -1332,143 +1338,83 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind assert(tbin->ncached == 0); -#ifdef JEMALLOC_PROF - malloc_mutex_lock(&arena->lock); - arena_prof_accum(arena, prof_accumbytes); - malloc_mutex_unlock(&arena->lock); -#endif + if (config_prof && arena_prof_accum(arena, prof_accumbytes)) + prof_idump(); bin = &arena->bins[binind]; malloc_mutex_lock(&bin->lock); - for (i = 0, nfill = (tbin->ncached_max >> 1); i < nfill; i++) { + for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >> + tbin->lg_fill_div); i < nfill; i++) { if ((run = bin->runcur) != NULL && run->nfree > 0) - ptr = arena_run_reg_alloc(run, bin); + ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]); else ptr = arena_bin_malloc_hard(arena, bin); if (ptr == NULL) break; - *(void **)ptr = tbin->avail; - tbin->avail = ptr; - } -#ifdef JEMALLOC_STATS - bin->stats.allocated += (i - tbin->ncached) * bin->reg_size; - bin->stats.nmalloc += i; - bin->stats.nrequests += tbin->tstats.nrequests; - bin->stats.nfills++; - tbin->tstats.nrequests = 0; -#endif + if (config_fill && opt_junk) { + arena_alloc_junk_small(ptr, &arena_bin_info[binind], + true); + } + /* Insert such that low regions get used first. */ + tbin->avail[nfill - 1 - i] = ptr; + } + if (config_stats) { + bin->stats.allocated += i * arena_bin_info[binind].reg_size; + bin->stats.nmalloc += i; + bin->stats.nrequests += tbin->tstats.nrequests; + bin->stats.nfills++; + tbin->tstats.nrequests = 0; + } malloc_mutex_unlock(&bin->lock); tbin->ncached = i; - if (tbin->ncached > tbin->high_water) - tbin->high_water = tbin->ncached; } -#endif -/* - * Calculate bin->run_size such that it meets the following constraints: - * - * *) bin->run_size >= min_run_size - * *) bin->run_size <= arena_maxclass - * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). - * *) run header size < PAGE_SIZE - * - * bin->nregs and bin->reg0_offset are also calculated here, since these - * settings are all interdependent. - */ -static size_t -arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size) +void +arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero) { - size_t try_run_size, good_run_size; - uint32_t try_nregs, good_nregs; - uint32_t try_hdr_size, good_hdr_size; -#ifdef JEMALLOC_PROF - uint32_t try_ctx0_offset, good_ctx0_offset; -#endif - uint32_t try_reg0_offset, good_reg0_offset; - - assert(min_run_size >= PAGE_SIZE); - assert(min_run_size <= arena_maxclass); - - /* - * Calculate known-valid settings before entering the run_size - * expansion loop, so that the first part of the loop always copies - * valid settings. - * - * The do..while loop iteratively reduces the number of regions until - * the run header and the regions no longer overlap. A closed formula - * would be quite messy, since there is an interdependency between the - * header's mask length and the number of regions. - */ - try_run_size = min_run_size; - try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) - + 1; /* Counter-act try_nregs-- in loop. */ - do { - try_nregs--; - try_hdr_size = sizeof(arena_run_t); -#ifdef JEMALLOC_PROF - if (opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* Add space for one (prof_ctx_t *) per region. */ - try_hdr_size += try_nregs * sizeof(prof_ctx_t *); - } else - try_ctx0_offset = 0; -#endif - try_reg0_offset = try_run_size - (try_nregs * bin->reg_size); - } while (try_hdr_size > try_reg0_offset); - /* run_size expansion loop. */ - do { - /* - * Copy valid settings before trying more aggressive settings. - */ - good_run_size = try_run_size; - good_nregs = try_nregs; - good_hdr_size = try_hdr_size; -#ifdef JEMALLOC_PROF - good_ctx0_offset = try_ctx0_offset; -#endif - good_reg0_offset = try_reg0_offset; - - /* Try more aggressive settings. */ - try_run_size += PAGE_SIZE; - try_nregs = ((try_run_size - sizeof(arena_run_t)) / - bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */ - do { - try_nregs--; - try_hdr_size = sizeof(arena_run_t); -#ifdef JEMALLOC_PROF - if (opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* - * Add space for one (prof_ctx_t *) per region. - */ - try_hdr_size += try_nregs * - sizeof(prof_ctx_t *); - } -#endif - try_reg0_offset = try_run_size - (try_nregs * - bin->reg_size); - } while (try_hdr_size > try_reg0_offset); - } while (try_run_size <= arena_maxclass - && try_run_size <= arena_maxclass - && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX - && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size - && try_hdr_size < PAGE_SIZE); - - assert(good_hdr_size <= good_reg0_offset); + if (zero) { + size_t redzone_size = bin_info->redzone_size; + memset((void *)((uintptr_t)ptr - redzone_size), 0xa5, + redzone_size); + memset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5, + redzone_size); + } else { + memset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5, + bin_info->reg_interval); + } +} - /* Copy final settings. */ - bin->run_size = good_run_size; - bin->nregs = good_nregs; -#ifdef JEMALLOC_PROF - bin->ctx0_offset = good_ctx0_offset; -#endif - bin->reg0_offset = good_reg0_offset; +void +arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info) +{ + size_t size = bin_info->reg_size; + size_t redzone_size = bin_info->redzone_size; + size_t i; + bool error = false; + + for (i = 1; i <= redzone_size; i++) { + unsigned byte; + if ((byte = *(uint8_t *)((uintptr_t)ptr - i)) != 0xa5) { + error = true; + malloc_printf("<jemalloc>: Corrupt redzone " + "%zu byte%s before %p (size %zu), byte=%#x\n", i, + (i == 1) ? "" : "s", ptr, size, byte); + } + } + for (i = 0; i < redzone_size; i++) { + unsigned byte; + if ((byte = *(uint8_t *)((uintptr_t)ptr + size + i)) != 0xa5) { + error = true; + malloc_printf("<jemalloc>: Corrupt redzone " + "%zu byte%s after end of %p (size %zu), byte=%#x\n", + i, (i == 1) ? "" : "s", ptr, size, byte); + } + } + if (opt_abort && error) + abort(); - return (good_run_size); + memset((void *)((uintptr_t)ptr - redzone_size), 0x5a, + bin_info->reg_interval); } void * @@ -1479,14 +1425,14 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero) arena_run_t *run; size_t binind; - binind = small_size2bin[size]; - assert(binind < nbins); + binind = SMALL_SIZE2BIN(size); + assert(binind < NBINS); bin = &arena->bins[binind]; - size = bin->reg_size; + size = arena_bin_info[binind].reg_size; malloc_mutex_lock(&bin->lock); if ((run = bin->runcur) != NULL && run->nfree > 0) - ret = arena_run_reg_alloc(run, bin); + ret = arena_run_reg_alloc(run, &arena_bin_info[binind]); else ret = arena_bin_malloc_hard(arena, bin); @@ -1495,29 +1441,32 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero) return (NULL); } -#ifdef JEMALLOC_STATS - bin->stats.allocated += size; - bin->stats.nmalloc++; - bin->stats.nrequests++; -#endif - malloc_mutex_unlock(&bin->lock); -#ifdef JEMALLOC_PROF - if (isthreaded == false) { - malloc_mutex_lock(&arena->lock); - arena_prof_accum(arena, size); - malloc_mutex_unlock(&arena->lock); + if (config_stats) { + bin->stats.allocated += size; + bin->stats.nmalloc++; + bin->stats.nrequests++; } -#endif + malloc_mutex_unlock(&bin->lock); + if (config_prof && isthreaded == false && arena_prof_accum(arena, size)) + prof_idump(); if (zero == false) { -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); -#endif - } else + if (config_fill) { + if (opt_junk) { + arena_alloc_junk_small(ret, + &arena_bin_info[binind], false); + } else if (opt_zero) + memset(ret, 0, size); + } + } else { + if (config_fill && opt_junk) { + arena_alloc_junk_small(ret, &arena_bin_info[binind], + true); + } + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); memset(ret, 0, size); + } + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); return (ret); } @@ -1526,242 +1475,119 @@ void * arena_malloc_large(arena_t *arena, size_t size, bool zero) { void *ret; + UNUSED bool idump; /* Large allocation. */ size = PAGE_CEILING(size); malloc_mutex_lock(&arena->lock); - ret = (void *)arena_run_alloc(arena, size, true, zero); + ret = (void *)arena_run_alloc(arena, size, true, BININD_INVALID, zero); if (ret == NULL) { malloc_mutex_unlock(&arena->lock); return (NULL); } -#ifdef JEMALLOC_STATS - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nmalloc++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif -#ifdef JEMALLOC_PROF - arena_prof_accum(arena, size); -#endif + if (config_stats) { + arena->stats.nmalloc_large++; + arena->stats.nrequests_large++; + arena->stats.allocated_large += size; + arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; + arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; + arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; + } + if (config_prof) + idump = arena_prof_accum_locked(arena, size); malloc_mutex_unlock(&arena->lock); + if (config_prof && idump) + prof_idump(); if (zero == false) { -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); -#endif + if (config_fill) { + if (opt_junk) + memset(ret, 0xa5, size); + else if (opt_zero) + memset(ret, 0, size); + } } return (ret); } -void * -arena_malloc(size_t size, bool zero) -{ - - assert(size != 0); - assert(QUANTUM_CEILING(size) <= arena_maxclass); - - if (size <= small_maxclass) { -#ifdef JEMALLOC_TCACHE - tcache_t *tcache; - - if ((tcache = tcache_get()) != NULL) - return (tcache_alloc_small(tcache, size, zero)); - else - -#endif - return (arena_malloc_small(choose_arena(), size, zero)); - } else { -#ifdef JEMALLOC_TCACHE - if (size <= tcache_maxclass) { - tcache_t *tcache; - - if ((tcache = tcache_get()) != NULL) - return (tcache_alloc_large(tcache, size, zero)); - else { - return (arena_malloc_large(choose_arena(), - size, zero)); - } - } else -#endif - return (arena_malloc_large(choose_arena(), size, zero)); - } -} - /* Only handles large allocations that require more than page alignment. */ void * -arena_palloc(arena_t *arena, size_t size, size_t alloc_size, size_t alignment, - bool zero) +arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero) { void *ret; - size_t offset; + size_t alloc_size, leadsize, trailsize; + arena_run_t *run; arena_chunk_t *chunk; assert((size & PAGE_MASK) == 0); alignment = PAGE_CEILING(alignment); + alloc_size = size + alignment - PAGE; malloc_mutex_lock(&arena->lock); - ret = (void *)arena_run_alloc(arena, alloc_size, true, zero); - if (ret == NULL) { + run = arena_run_alloc(arena, alloc_size, true, BININD_INVALID, zero); + if (run == NULL) { malloc_mutex_unlock(&arena->lock); return (NULL); } + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); - - offset = (uintptr_t)ret & (alignment - 1); - assert((offset & PAGE_MASK) == 0); - assert(offset < alloc_size); - if (offset == 0) - arena_run_trim_tail(arena, chunk, ret, alloc_size, size, false); - else { - size_t leadsize, trailsize; - - leadsize = alignment - offset; - if (leadsize > 0) { - arena_run_trim_head(arena, chunk, ret, alloc_size, - alloc_size - leadsize); - ret = (void *)((uintptr_t)ret + leadsize); - } - - trailsize = alloc_size - leadsize - size; - if (trailsize != 0) { - /* Trim trailing space. */ - assert(trailsize < alloc_size); - arena_run_trim_tail(arena, chunk, ret, size + trailsize, - size, false); - } + leadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) - + (uintptr_t)run; + assert(alloc_size >= leadsize + size); + trailsize = alloc_size - leadsize - size; + ret = (void *)((uintptr_t)run + leadsize); + if (leadsize != 0) { + arena_run_trim_head(arena, chunk, run, alloc_size, alloc_size - + leadsize); + } + if (trailsize != 0) { + arena_run_trim_tail(arena, chunk, ret, size + trailsize, size, + false); } -#ifdef JEMALLOC_STATS - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nmalloc++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; + if (config_stats) { + arena->stats.nmalloc_large++; + arena->stats.nrequests_large++; + arena->stats.allocated_large += size; + arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; + arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; + arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; } -#endif malloc_mutex_unlock(&arena->lock); -#ifdef JEMALLOC_FILL - if (zero == false) { + if (config_fill && zero == false) { if (opt_junk) memset(ret, 0xa5, size); else if (opt_zero) memset(ret, 0, size); } -#endif return (ret); } -/* Return the size of the allocation pointed to by ptr. */ -size_t -arena_salloc(const void *ptr) -{ - size_t ret; - arena_chunk_t *chunk; - size_t pageind, mapbits; - - assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapbits = chunk->map[pageind-map_bias].bits; - assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapbits & CHUNK_MAP_LARGE) == 0) { - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> PAGE_SHIFT)) << - PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - assert(((uintptr_t)ptr - ((uintptr_t)run + - (uintptr_t)run->bin->reg0_offset)) % run->bin->reg_size == - 0); - ret = run->bin->reg_size; - } else { - assert(((uintptr_t)ptr & PAGE_MASK) == 0); - ret = mapbits & ~PAGE_MASK; - assert(ret != 0); - } - - return (ret); -} - -#ifdef JEMALLOC_PROF void arena_prof_promoted(const void *ptr, size_t size) { arena_chunk_t *chunk; size_t pageind, binind; + cassert(config_prof); assert(ptr != NULL); assert(CHUNK_ADDR2BASE(ptr) != ptr); - assert(isalloc(ptr) == PAGE_SIZE); + assert(isalloc(ptr, false) == PAGE); + assert(isalloc(ptr, true) == PAGE); + assert(size <= SMALL_MAXCLASS); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - binind = small_size2bin[size]; - assert(binind < nbins); - chunk->map[pageind-map_bias].bits = (chunk->map[pageind-map_bias].bits & - ~CHUNK_MAP_CLASS_MASK) | ((binind+1) << CHUNK_MAP_CLASS_SHIFT); -} + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + binind = SMALL_SIZE2BIN(size); + assert(binind < NBINS); + arena_mapbits_large_binind_set(chunk, pageind, binind); -size_t -arena_salloc_demote(const void *ptr) -{ - size_t ret; - arena_chunk_t *chunk; - size_t pageind, mapbits; - - assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - mapbits = chunk->map[pageind-map_bias].bits; - assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapbits & CHUNK_MAP_LARGE) == 0) { - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapbits >> PAGE_SHIFT)) << - PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - assert(((uintptr_t)ptr - ((uintptr_t)run + - (uintptr_t)run->bin->reg0_offset)) % run->bin->reg_size == - 0); - ret = run->bin->reg_size; - } else { - assert(((uintptr_t)ptr & PAGE_MASK) == 0); - ret = mapbits & ~PAGE_MASK; - if (prof_promote && ret == PAGE_SIZE && (mapbits & - CHUNK_MAP_CLASS_MASK) != 0) { - size_t binind = ((mapbits & CHUNK_MAP_CLASS_MASK) >> - CHUNK_MAP_CLASS_SHIFT) - 1; - assert(binind < nbins); - ret = chunk->arena->bins[binind].reg_size; - } - assert(ret != 0); - } - - return (ret); + assert(isalloc(ptr, false) == PAGE); + assert(isalloc(ptr, true) == size); } -#endif static void arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, @@ -1771,17 +1597,18 @@ arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, /* Dissociate run from bin. */ if (run == bin->runcur) bin->runcur = NULL; - else if (bin->nregs != 1) { - size_t run_pageind = (((uintptr_t)run - (uintptr_t)chunk)) >> - PAGE_SHIFT; - arena_chunk_map_t *run_mapelm = - &chunk->map[run_pageind-map_bias]; - /* - * This block's conditional is necessary because if the run - * only contains one region, then it never gets inserted into - * the non-full runs tree. - */ - arena_run_tree_remove(&bin->runs, run_mapelm); + else { + size_t binind = arena_bin_index(chunk->arena, bin); + arena_bin_info_t *bin_info = &arena_bin_info[binind]; + + if (bin_info->nregs != 1) { + /* + * This block's conditional is necessary because if the + * run only contains one region, then it never gets + * inserted into the non-full runs tree. + */ + arena_bin_runs_remove(bin, run); + } } } @@ -1789,18 +1616,26 @@ static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, arena_bin_t *bin) { + size_t binind; + arena_bin_info_t *bin_info; size_t npages, run_ind, past; assert(run != bin->runcur); - assert(arena_run_tree_search(&bin->runs, &chunk->map[ - (((uintptr_t)run-(uintptr_t)chunk)>>PAGE_SHIFT)-map_bias]) == NULL); + assert(arena_run_tree_search(&bin->runs, + arena_mapp_get(chunk, ((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE)) + == NULL); + + binind = arena_bin_index(chunk->arena, run->bin); + bin_info = &arena_bin_info[binind]; malloc_mutex_unlock(&bin->lock); /******************************/ - npages = bin->run_size >> PAGE_SHIFT; - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT); - past = (size_t)((PAGE_CEILING((uintptr_t)run->next) - (uintptr_t)chunk) - >> PAGE_SHIFT); + npages = bin_info->run_size >> LG_PAGE; + run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); + past = (size_t)(PAGE_CEILING((uintptr_t)run + + (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind * + bin_info->reg_interval - bin_info->redzone_size) - + (uintptr_t)chunk) >> LG_PAGE); malloc_mutex_lock(&arena->lock); /* @@ -1808,32 +1643,24 @@ arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, * trim the clean pages before deallocating the dirty portion of the * run. */ - if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) == 0 && past - - run_ind < npages) { - /* - * Trim clean pages. Convert to large run beforehand. Set the - * last map element first, in case this is a one-page run. - */ - chunk->map[run_ind+npages-1-map_bias].bits = CHUNK_MAP_LARGE | - (chunk->map[run_ind+npages-1-map_bias].bits & - CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind-map_bias].bits = bin->run_size | - CHUNK_MAP_LARGE | (chunk->map[run_ind-map_bias].bits & - CHUNK_MAP_FLAGS_MASK); - arena_run_trim_tail(arena, chunk, run, (npages << PAGE_SHIFT), - ((past - run_ind) << PAGE_SHIFT), false); + assert(arena_mapbits_dirty_get(chunk, run_ind) == + arena_mapbits_dirty_get(chunk, run_ind+npages-1)); + if (arena_mapbits_dirty_get(chunk, run_ind) == 0 && past - run_ind < + npages) { + /* Trim clean pages. Convert to large run beforehand. */ + assert(npages > 0); + arena_mapbits_large_set(chunk, run_ind, bin_info->run_size, 0); + arena_mapbits_large_set(chunk, run_ind+npages-1, 0, 0); + arena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE), + ((past - run_ind) << LG_PAGE), false); /* npages = past - run_ind; */ } -#ifdef JEMALLOC_DEBUG - run->magic = 0; -#endif - arena_run_dalloc(arena, run, true); + arena_run_dalloc(arena, run, true, false); malloc_mutex_unlock(&arena->lock); /****************************/ malloc_mutex_lock(&bin->lock); -#ifdef JEMALLOC_STATS - bin->stats.curruns--; -#endif + if (config_stats) + bin->stats.curruns--; } static void @@ -1842,157 +1669,114 @@ arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, { /* - * Make sure that bin->runcur always refers to the lowest non-full run, - * if one exists. + * Make sure that if bin->runcur is non-NULL, it refers to the lowest + * non-full run. It is okay to NULL runcur out rather than proactively + * keeping it pointing at the lowest non-full run. */ - if (bin->runcur == NULL) - bin->runcur = run; - else if ((uintptr_t)run < (uintptr_t)bin->runcur) { + if ((uintptr_t)run < (uintptr_t)bin->runcur) { /* Switch runcur. */ - if (bin->runcur->nfree > 0) { - arena_chunk_t *runcur_chunk = - CHUNK_ADDR2BASE(bin->runcur); - size_t runcur_pageind = (((uintptr_t)bin->runcur - - (uintptr_t)runcur_chunk)) >> PAGE_SHIFT; - arena_chunk_map_t *runcur_mapelm = - &runcur_chunk->map[runcur_pageind-map_bias]; - - /* Insert runcur. */ - arena_run_tree_insert(&bin->runs, runcur_mapelm); - } + if (bin->runcur->nfree > 0) + arena_bin_runs_insert(bin, bin->runcur); bin->runcur = run; - } else { - size_t run_pageind = (((uintptr_t)run - - (uintptr_t)chunk)) >> PAGE_SHIFT; - arena_chunk_map_t *run_mapelm = - &chunk->map[run_pageind-map_bias]; - - assert(arena_run_tree_search(&bin->runs, run_mapelm) == NULL); - arena_run_tree_insert(&bin->runs, run_mapelm); - } + if (config_stats) + bin->stats.reruns++; + } else + arena_bin_runs_insert(bin, run); } void -arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, +arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr, arena_chunk_map_t *mapelm) { size_t pageind; arena_run_t *run; arena_bin_t *bin; -#if (defined(JEMALLOC_FILL) || defined(JEMALLOC_STATS)) - size_t size; -#endif + arena_bin_info_t *bin_info; + size_t size, binind; - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; + pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - (mapelm->bits >> PAGE_SHIFT)) << PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); + arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); bin = run->bin; -#if (defined(JEMALLOC_FILL) || defined(JEMALLOC_STATS)) - size = bin->reg_size; -#endif + binind = arena_ptr_small_binind_get(ptr, mapelm->bits); + bin_info = &arena_bin_info[binind]; + if (config_fill || config_stats) + size = bin_info->reg_size; -#ifdef JEMALLOC_FILL - if (opt_junk) - memset(ptr, 0x5a, size); -#endif + if (config_fill && opt_junk) + arena_dalloc_junk_small(ptr, bin_info); arena_run_reg_dalloc(run, ptr); - if (run->nfree == bin->nregs) { + if (run->nfree == bin_info->nregs) { arena_dissociate_bin_run(chunk, run, bin); arena_dalloc_bin_run(arena, chunk, run, bin); } else if (run->nfree == 1 && run != bin->runcur) arena_bin_lower_run(arena, chunk, run, bin); -#ifdef JEMALLOC_STATS - bin->stats.allocated -= size; - bin->stats.ndalloc++; -#endif + if (config_stats) { + bin->stats.allocated -= size; + bin->stats.ndalloc++; + } } -#ifdef JEMALLOC_STATS void -arena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty, - arena_stats_t *astats, malloc_bin_stats_t *bstats, - malloc_large_stats_t *lstats) +arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, + size_t pageind, arena_chunk_map_t *mapelm) { - unsigned i; + arena_run_t *run; + arena_bin_t *bin; - malloc_mutex_lock(&arena->lock); - *nactive += arena->nactive; - *ndirty += arena->ndirty; + run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - + arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); + bin = run->bin; + malloc_mutex_lock(&bin->lock); + arena_dalloc_bin_locked(arena, chunk, ptr, mapelm); + malloc_mutex_unlock(&bin->lock); +} - astats->mapped += arena->stats.mapped; - astats->npurge += arena->stats.npurge; - astats->nmadvise += arena->stats.nmadvise; - astats->purged += arena->stats.purged; - astats->allocated_large += arena->stats.allocated_large; - astats->nmalloc_large += arena->stats.nmalloc_large; - astats->ndalloc_large += arena->stats.ndalloc_large; - astats->nrequests_large += arena->stats.nrequests_large; +void +arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, + size_t pageind) +{ + arena_chunk_map_t *mapelm; - for (i = 0; i < nlclasses; i++) { - lstats[i].nmalloc += arena->stats.lstats[i].nmalloc; - lstats[i].ndalloc += arena->stats.lstats[i].ndalloc; - lstats[i].nrequests += arena->stats.lstats[i].nrequests; - lstats[i].highruns += arena->stats.lstats[i].highruns; - lstats[i].curruns += arena->stats.lstats[i].curruns; + if (config_debug) { + /* arena_ptr_small_binind_get() does extra sanity checking. */ + assert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk, + pageind)) != BININD_INVALID); } - malloc_mutex_unlock(&arena->lock); + mapelm = arena_mapp_get(chunk, pageind); + arena_dalloc_bin(arena, chunk, ptr, pageind, mapelm); +} - for (i = 0; i < nbins; i++) { - arena_bin_t *bin = &arena->bins[i]; +void +arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr) +{ - malloc_mutex_lock(&bin->lock); - bstats[i].allocated += bin->stats.allocated; - bstats[i].nmalloc += bin->stats.nmalloc; - bstats[i].ndalloc += bin->stats.ndalloc; - bstats[i].nrequests += bin->stats.nrequests; -#ifdef JEMALLOC_TCACHE - bstats[i].nfills += bin->stats.nfills; - bstats[i].nflushes += bin->stats.nflushes; -#endif - bstats[i].nruns += bin->stats.nruns; - bstats[i].reruns += bin->stats.reruns; - bstats[i].highruns += bin->stats.highruns; - bstats[i].curruns += bin->stats.curruns; - malloc_mutex_unlock(&bin->lock); + if (config_fill || config_stats) { + size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + size_t size = arena_mapbits_large_size_get(chunk, pageind); + + if (config_fill && config_stats && opt_junk) + memset(ptr, 0x5a, size); + if (config_stats) { + arena->stats.ndalloc_large++; + arena->stats.allocated_large -= size; + arena->stats.lstats[(size >> LG_PAGE) - 1].ndalloc++; + arena->stats.lstats[(size >> LG_PAGE) - 1].curruns--; + } } + + arena_run_dalloc(arena, (arena_run_t *)ptr, true, false); } -#endif void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) { - /* Large allocation. */ -#ifdef JEMALLOC_FILL -# ifndef JEMALLOC_STATS - if (opt_junk) -# endif -#endif - { -#if (defined(JEMALLOC_FILL) || defined(JEMALLOC_STATS)) - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> - PAGE_SHIFT; - size_t size = chunk->map[pageind-map_bias].bits & ~PAGE_MASK; -#endif - -#ifdef JEMALLOC_FILL -# ifdef JEMALLOC_STATS - if (opt_junk) -# endif - memset(ptr, 0x5a, size); -#endif -#ifdef JEMALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].ndalloc++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns--; -#endif - } - - arena_run_dalloc(arena, (arena_run_t *)ptr, true); + malloc_mutex_lock(&arena->lock); + arena_dalloc_large_locked(arena, chunk, ptr); + malloc_mutex_unlock(&arena->lock); } static void @@ -2009,24 +1793,19 @@ arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, malloc_mutex_lock(&arena->lock); arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, true); -#ifdef JEMALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].ndalloc++; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--; - - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nmalloc++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif + if (config_stats) { + arena->stats.ndalloc_large++; + arena->stats.allocated_large -= oldsize; + arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++; + arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--; + + arena->stats.nmalloc_large++; + arena->stats.nrequests_large++; + arena->stats.allocated_large += size; + arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; + arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; + arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; + } malloc_mutex_unlock(&arena->lock); } @@ -2034,20 +1813,19 @@ static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, size_t oldsize, size_t size, size_t extra, bool zero) { - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t npages = oldsize >> PAGE_SHIFT; + size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; + size_t npages = oldsize >> LG_PAGE; size_t followsize; - assert(oldsize == (chunk->map[pageind-map_bias].bits & ~PAGE_MASK)); + assert(oldsize == arena_mapbits_large_size_get(chunk, pageind)); /* Try to extend the run. */ assert(size + extra > oldsize); malloc_mutex_lock(&arena->lock); if (pageind + npages < chunk_npages && - (chunk->map[pageind+npages-map_bias].bits - & CHUNK_MAP_ALLOCATED) == 0 && (followsize = - chunk->map[pageind+npages-map_bias].bits & ~PAGE_MASK) >= size - - oldsize) { + arena_mapbits_allocated_get(chunk, pageind+npages) == 0 && + (followsize = arena_mapbits_unallocated_size_get(chunk, + pageind+npages)) >= size - oldsize) { /* * The next run is available and sufficiently large. Split the * following run, then merge the first part with the existing @@ -2057,10 +1835,11 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, size_t splitsize = (oldsize + followsize <= size + extra) ? followsize : size + extra - oldsize; arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk + - ((pageind+npages) << PAGE_SHIFT)), splitsize, true, zero); + ((pageind+npages) << LG_PAGE)), splitsize, true, + BININD_INVALID, zero); size = oldsize + splitsize; - npages = size >> PAGE_SHIFT; + npages = size >> LG_PAGE; /* * Mark the extended run as dirty if either portion of the run @@ -2070,34 +1849,24 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, * arena_run_dalloc() with the dirty argument set to false * (which is when dirty flag consistency would really matter). */ - flag_dirty = (chunk->map[pageind-map_bias].bits & - CHUNK_MAP_DIRTY) | - (chunk->map[pageind+npages-1-map_bias].bits & - CHUNK_MAP_DIRTY); - chunk->map[pageind-map_bias].bits = size | flag_dirty - | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - chunk->map[pageind+npages-1-map_bias].bits = flag_dirty | - CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; - -#ifdef JEMALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].ndalloc++; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--; - - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nmalloc++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - - 1].curruns; + flag_dirty = arena_mapbits_dirty_get(chunk, pageind) | + arena_mapbits_dirty_get(chunk, pageind+npages-1); + arena_mapbits_large_set(chunk, pageind, size, flag_dirty); + arena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty); + + if (config_stats) { + arena->stats.ndalloc_large++; + arena->stats.allocated_large -= oldsize; + arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++; + arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--; + + arena->stats.nmalloc_large++; + arena->stats.nrequests_large++; + arena->stats.allocated_large += size; + arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; + arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; + arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; } -#endif malloc_mutex_unlock(&arena->lock); return (false); } @@ -2119,12 +1888,10 @@ arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, psize = PAGE_CEILING(size + extra); if (psize == oldsize) { /* Same size class. */ -#ifdef JEMALLOC_FILL - if (opt_junk && size < oldsize) { + if (config_fill && opt_junk && size < oldsize) { memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); } -#endif return (false); } else { arena_chunk_t *chunk; @@ -2132,16 +1899,13 @@ arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); arena = chunk->arena; - assert(arena->magic == ARENA_MAGIC); if (psize < oldsize) { -#ifdef JEMALLOC_FILL /* Fill before shrinking in order avoid a race. */ - if (opt_junk) { + if (config_fill && opt_junk) { memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); } -#endif arena_ralloc_large_shrink(arena, chunk, ptr, oldsize, psize); return (false); @@ -2149,12 +1913,11 @@ arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, bool ret = arena_ralloc_large_grow(arena, chunk, ptr, oldsize, PAGE_CEILING(size), psize - PAGE_CEILING(size), zero); -#ifdef JEMALLOC_FILL - if (ret == false && zero == false && opt_zero) { + if (config_fill && ret == false && zero == false && + opt_zero) { memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize); } -#endif return (ret); } } @@ -2169,24 +1932,22 @@ arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, * Avoid moving the allocation if the size class can be left the same. */ if (oldsize <= arena_maxclass) { - if (oldsize <= small_maxclass) { - assert(choose_arena()->bins[small_size2bin[ - oldsize]].reg_size == oldsize); - if ((size + extra <= small_maxclass && - small_size2bin[size + extra] == - small_size2bin[oldsize]) || (size <= oldsize && + if (oldsize <= SMALL_MAXCLASS) { + assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size + == oldsize); + if ((size + extra <= SMALL_MAXCLASS && + SMALL_SIZE2BIN(size + extra) == + SMALL_SIZE2BIN(oldsize)) || (size <= oldsize && size + extra >= oldsize)) { -#ifdef JEMALLOC_FILL - if (opt_junk && size < oldsize) { + if (config_fill && opt_junk && size < oldsize) { memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); } -#endif return (ptr); } } else { assert(size <= arena_maxclass); - if (size + extra > small_maxclass) { + if (size + extra > SMALL_MAXCLASS) { if (arena_ralloc_large(ptr, oldsize, size, extra, zero) == false) return (ptr); @@ -2199,8 +1960,9 @@ arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, } void * -arena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero) +arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, + size_t extra, size_t alignment, bool zero, bool try_tcache_alloc, + bool try_tcache_dalloc) { void *ret; size_t copysize; @@ -2210,25 +1972,31 @@ arena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, if (ret != NULL) return (ret); - /* * size and oldsize are different enough that we need to move the * object. In that case, fall back to allocating new space and * copying. */ - if (alignment != 0) - ret = ipalloc(size + extra, alignment, zero); - else - ret = arena_malloc(size + extra, zero); + if (alignment != 0) { + size_t usize = sa2u(size + extra, alignment); + if (usize == 0) + return (NULL); + ret = ipallocx(usize, alignment, zero, try_tcache_alloc, arena); + } else + ret = arena_malloc(arena, size + extra, zero, try_tcache_alloc); if (ret == NULL) { if (extra == 0) return (NULL); /* Try again, this time without extra. */ - if (alignment != 0) - ret = ipalloc(size, alignment, zero); - else - ret = arena_malloc(size, zero); + if (alignment != 0) { + size_t usize = sa2u(size, alignment); + if (usize == 0) + return (NULL); + ret = ipallocx(usize, alignment, zero, try_tcache_alloc, + arena); + } else + ret = arena_malloc(arena, size, zero, try_tcache_alloc); if (ret == NULL) return (NULL); @@ -2241,313 +2009,305 @@ arena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, * expectation that the extra bytes will be reliably preserved. */ copysize = (size < oldsize) ? size : oldsize; + VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize); memcpy(ret, ptr, copysize); - idalloc(ptr); + iqallocx(ptr, try_tcache_dalloc); + return (ret); +} + +dss_prec_t +arena_dss_prec_get(arena_t *arena) +{ + dss_prec_t ret; + + malloc_mutex_lock(&arena->lock); + ret = arena->dss_prec; + malloc_mutex_unlock(&arena->lock); return (ret); } +void +arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) +{ + + malloc_mutex_lock(&arena->lock); + arena->dss_prec = dss_prec; + malloc_mutex_unlock(&arena->lock); +} + +void +arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, + size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats, + malloc_large_stats_t *lstats) +{ + unsigned i; + + malloc_mutex_lock(&arena->lock); + *dss = dss_prec_names[arena->dss_prec]; + *nactive += arena->nactive; + *ndirty += arena->ndirty; + + astats->mapped += arena->stats.mapped; + astats->npurge += arena->stats.npurge; + astats->nmadvise += arena->stats.nmadvise; + astats->purged += arena->stats.purged; + astats->allocated_large += arena->stats.allocated_large; + astats->nmalloc_large += arena->stats.nmalloc_large; + astats->ndalloc_large += arena->stats.ndalloc_large; + astats->nrequests_large += arena->stats.nrequests_large; + + for (i = 0; i < nlclasses; i++) { + lstats[i].nmalloc += arena->stats.lstats[i].nmalloc; + lstats[i].ndalloc += arena->stats.lstats[i].ndalloc; + lstats[i].nrequests += arena->stats.lstats[i].nrequests; + lstats[i].curruns += arena->stats.lstats[i].curruns; + } + malloc_mutex_unlock(&arena->lock); + + for (i = 0; i < NBINS; i++) { + arena_bin_t *bin = &arena->bins[i]; + + malloc_mutex_lock(&bin->lock); + bstats[i].allocated += bin->stats.allocated; + bstats[i].nmalloc += bin->stats.nmalloc; + bstats[i].ndalloc += bin->stats.ndalloc; + bstats[i].nrequests += bin->stats.nrequests; + if (config_tcache) { + bstats[i].nfills += bin->stats.nfills; + bstats[i].nflushes += bin->stats.nflushes; + } + bstats[i].nruns += bin->stats.nruns; + bstats[i].reruns += bin->stats.reruns; + bstats[i].curruns += bin->stats.curruns; + malloc_mutex_unlock(&bin->lock); + } +} + bool arena_new(arena_t *arena, unsigned ind) { unsigned i; arena_bin_t *bin; - size_t prev_run_size; arena->ind = ind; + arena->nthreads = 0; if (malloc_mutex_init(&arena->lock)) return (true); -#ifdef JEMALLOC_STATS - memset(&arena->stats, 0, sizeof(arena_stats_t)); - arena->stats.lstats = (malloc_large_stats_t *)base_alloc(nlclasses * - sizeof(malloc_large_stats_t)); - if (arena->stats.lstats == NULL) - return (true); - memset(arena->stats.lstats, 0, nlclasses * - sizeof(malloc_large_stats_t)); -# ifdef JEMALLOC_TCACHE - ql_new(&arena->tcache_ql); -# endif -#endif + if (config_stats) { + memset(&arena->stats, 0, sizeof(arena_stats_t)); + arena->stats.lstats = + (malloc_large_stats_t *)base_alloc(nlclasses * + sizeof(malloc_large_stats_t)); + if (arena->stats.lstats == NULL) + return (true); + memset(arena->stats.lstats, 0, nlclasses * + sizeof(malloc_large_stats_t)); + if (config_tcache) + ql_new(&arena->tcache_ql); + } -#ifdef JEMALLOC_PROF - arena->prof_accumbytes = 0; -#endif + if (config_prof) + arena->prof_accumbytes = 0; + + arena->dss_prec = chunk_dss_prec_get(); /* Initialize chunks. */ - ql_new(&arena->chunks_dirty); + arena_chunk_dirty_new(&arena->chunks_dirty); arena->spare = NULL; arena->nactive = 0; arena->ndirty = 0; arena->npurgatory = 0; - arena_avail_tree_new(&arena->runs_avail_clean); - arena_avail_tree_new(&arena->runs_avail_dirty); + arena_avail_tree_new(&arena->runs_avail); /* Initialize bins. */ - prev_run_size = PAGE_SIZE; - - i = 0; -#ifdef JEMALLOC_TINY - /* (2^n)-spaced tiny bins. */ - for (; i < ntbins; i++) { + for (i = 0; i < NBINS; i++) { bin = &arena->bins[i]; if (malloc_mutex_init(&bin->lock)) return (true); bin->runcur = NULL; arena_run_tree_new(&bin->runs); - - bin->reg_size = (1U << (LG_TINY_MIN + i)); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef JEMALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif + if (config_stats) + memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); } -#endif - /* Quantum-spaced bins. */ - for (; i < ntbins + nqbins; i++) { - bin = &arena->bins[i]; - if (malloc_mutex_init(&bin->lock)) - return (true); - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); + return (false); +} - bin->reg_size = (i - ntbins + 1) << LG_QUANTUM; +/* + * Calculate bin_info->run_size such that it meets the following constraints: + * + * *) bin_info->run_size >= min_run_size + * *) bin_info->run_size <= arena_maxclass + * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). + * *) bin_info->nregs <= RUN_MAXREGS + * + * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also + * calculated here, since these settings are all interdependent. + */ +static size_t +bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) +{ + size_t pad_size; + size_t try_run_size, good_run_size; + uint32_t try_nregs, good_nregs; + uint32_t try_hdr_size, good_hdr_size; + uint32_t try_bitmap_offset, good_bitmap_offset; + uint32_t try_ctx0_offset, good_ctx0_offset; + uint32_t try_redzone0_offset, good_redzone0_offset; - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); + assert(min_run_size >= PAGE); + assert(min_run_size <= arena_maxclass); -#ifdef JEMALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif + /* + * Determine redzone size based on minimum alignment and minimum + * redzone size. Add padding to the end of the run if it is needed to + * align the regions. The padding allows each redzone to be half the + * minimum alignment; without the padding, each redzone would have to + * be twice as large in order to maintain alignment. + */ + if (config_fill && opt_redzone) { + size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1); + if (align_min <= REDZONE_MINSIZE) { + bin_info->redzone_size = REDZONE_MINSIZE; + pad_size = 0; + } else { + bin_info->redzone_size = align_min >> 1; + pad_size = bin_info->redzone_size; + } + } else { + bin_info->redzone_size = 0; + pad_size = 0; } + bin_info->reg_interval = bin_info->reg_size + + (bin_info->redzone_size << 1); - /* Cacheline-spaced bins. */ - for (; i < ntbins + nqbins + ncbins; i++) { - bin = &arena->bins[i]; - if (malloc_mutex_init(&bin->lock)) - return (true); - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = cspace_min + ((i - (ntbins + nqbins)) << - LG_CACHELINE); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef JEMALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif + /* + * Calculate known-valid settings before entering the run_size + * expansion loop, so that the first part of the loop always copies + * valid settings. + * + * The do..while loop iteratively reduces the number of regions until + * the run header and the regions no longer overlap. A closed formula + * would be quite messy, since there is an interdependency between the + * header's mask length and the number of regions. + */ + try_run_size = min_run_size; + try_nregs = ((try_run_size - sizeof(arena_run_t)) / + bin_info->reg_interval) + + 1; /* Counter-act try_nregs-- in loop. */ + if (try_nregs > RUN_MAXREGS) { + try_nregs = RUN_MAXREGS + + 1; /* Counter-act try_nregs-- in loop. */ } + do { + try_nregs--; + try_hdr_size = sizeof(arena_run_t); + /* Pad to a long boundary. */ + try_hdr_size = LONG_CEILING(try_hdr_size); + try_bitmap_offset = try_hdr_size; + /* Add space for bitmap. */ + try_hdr_size += bitmap_size(try_nregs); + if (config_prof && opt_prof && prof_promote == false) { + /* Pad to a quantum boundary. */ + try_hdr_size = QUANTUM_CEILING(try_hdr_size); + try_ctx0_offset = try_hdr_size; + /* Add space for one (prof_ctx_t *) per region. */ + try_hdr_size += try_nregs * sizeof(prof_ctx_t *); + } else + try_ctx0_offset = 0; + try_redzone0_offset = try_run_size - (try_nregs * + bin_info->reg_interval) - pad_size; + } while (try_hdr_size > try_redzone0_offset); - /* Subpage-spaced bins. */ - for (; i < nbins; i++) { - bin = &arena->bins[i]; - if (malloc_mutex_init(&bin->lock)) - return (true); - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); + /* run_size expansion loop. */ + do { + /* + * Copy valid settings before trying more aggressive settings. + */ + good_run_size = try_run_size; + good_nregs = try_nregs; + good_hdr_size = try_hdr_size; + good_bitmap_offset = try_bitmap_offset; + good_ctx0_offset = try_ctx0_offset; + good_redzone0_offset = try_redzone0_offset; - bin->reg_size = sspace_min + ((i - (ntbins + nqbins + ncbins)) - << LG_SUBPAGE); + /* Try more aggressive settings. */ + try_run_size += PAGE; + try_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) / + bin_info->reg_interval) + + 1; /* Counter-act try_nregs-- in loop. */ + if (try_nregs > RUN_MAXREGS) { + try_nregs = RUN_MAXREGS + + 1; /* Counter-act try_nregs-- in loop. */ + } + do { + try_nregs--; + try_hdr_size = sizeof(arena_run_t); + /* Pad to a long boundary. */ + try_hdr_size = LONG_CEILING(try_hdr_size); + try_bitmap_offset = try_hdr_size; + /* Add space for bitmap. */ + try_hdr_size += bitmap_size(try_nregs); + if (config_prof && opt_prof && prof_promote == false) { + /* Pad to a quantum boundary. */ + try_hdr_size = QUANTUM_CEILING(try_hdr_size); + try_ctx0_offset = try_hdr_size; + /* + * Add space for one (prof_ctx_t *) per region. + */ + try_hdr_size += try_nregs * + sizeof(prof_ctx_t *); + } + try_redzone0_offset = try_run_size - (try_nregs * + bin_info->reg_interval) - pad_size; + } while (try_hdr_size > try_redzone0_offset); + } while (try_run_size <= arena_maxclass + && try_run_size <= arena_maxclass + && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) > + RUN_MAX_OVRHD_RELAX + && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size + && try_nregs < RUN_MAXREGS); - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); + assert(good_hdr_size <= good_redzone0_offset); -#ifdef JEMALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } + /* Copy final settings. */ + bin_info->run_size = good_run_size; + bin_info->nregs = good_nregs; + bin_info->bitmap_offset = good_bitmap_offset; + bin_info->ctx0_offset = good_ctx0_offset; + bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size; -#ifdef JEMALLOC_DEBUG - arena->magic = ARENA_MAGIC; -#endif + assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs + * bin_info->reg_interval) + pad_size == bin_info->run_size); - return (false); + return (good_run_size); } -#ifdef JEMALLOC_DEBUG static void -small_size2bin_validate(void) +bin_info_init(void) { - size_t i, size, binind; - - assert(small_size2bin[0] == 0xffU); - i = 1; -# ifdef JEMALLOC_TINY - /* Tiny. */ - for (; i < (1U << LG_TINY_MIN); i++) { - size = pow2_ceil(1U << LG_TINY_MIN); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - assert(small_size2bin[i] == binind); - } - for (; i < qspace_min; i++) { - size = pow2_ceil(i); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - assert(small_size2bin[i] == binind); - } -# endif - /* Quantum-spaced. */ - for (; i <= qspace_max; i++) { - size = QUANTUM_CEILING(i); - binind = ntbins + (size >> LG_QUANTUM) - 1; - assert(small_size2bin[i] == binind); - } - /* Cacheline-spaced. */ - for (; i <= cspace_max; i++) { - size = CACHELINE_CEILING(i); - binind = ntbins + nqbins + ((size - cspace_min) >> - LG_CACHELINE); - assert(small_size2bin[i] == binind); - } - /* Sub-page. */ - for (; i <= sspace_max; i++) { - size = SUBPAGE_CEILING(i); - binind = ntbins + nqbins + ncbins + ((size - sspace_min) - >> LG_SUBPAGE); - assert(small_size2bin[i] == binind); - } + arena_bin_info_t *bin_info; + size_t prev_run_size = PAGE; + +#define SIZE_CLASS(bin, delta, size) \ + bin_info = &arena_bin_info[bin]; \ + bin_info->reg_size = size; \ + prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\ + bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs); + SIZE_CLASSES +#undef SIZE_CLASS } -#endif -static bool -small_size2bin_init(void) -{ - - if (opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT - || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT - || sizeof(const_small_size2bin) != small_maxclass + 1) - return (small_size2bin_init_hard()); - - small_size2bin = const_small_size2bin; -#ifdef JEMALLOC_DEBUG - assert(sizeof(const_small_size2bin) == small_maxclass + 1); - small_size2bin_validate(); -#endif - return (false); -} - -static bool -small_size2bin_init_hard(void) -{ - size_t i, size, binind; - uint8_t *custom_small_size2bin; - - assert(opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT - || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT - || sizeof(const_small_size2bin) != small_maxclass + 1); - - custom_small_size2bin = (uint8_t *)base_alloc(small_maxclass + 1); - if (custom_small_size2bin == NULL) - return (true); - - custom_small_size2bin[0] = 0xffU; - i = 1; -#ifdef JEMALLOC_TINY - /* Tiny. */ - for (; i < (1U << LG_TINY_MIN); i++) { - size = pow2_ceil(1U << LG_TINY_MIN); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - custom_small_size2bin[i] = binind; - } - for (; i < qspace_min; i++) { - size = pow2_ceil(i); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - custom_small_size2bin[i] = binind; - } -#endif - /* Quantum-spaced. */ - for (; i <= qspace_max; i++) { - size = QUANTUM_CEILING(i); - binind = ntbins + (size >> LG_QUANTUM) - 1; - custom_small_size2bin[i] = binind; - } - /* Cacheline-spaced. */ - for (; i <= cspace_max; i++) { - size = CACHELINE_CEILING(i); - binind = ntbins + nqbins + ((size - cspace_min) >> - LG_CACHELINE); - custom_small_size2bin[i] = binind; - } - /* Sub-page. */ - for (; i <= sspace_max; i++) { - size = SUBPAGE_CEILING(i); - binind = ntbins + nqbins + ncbins + ((size - sspace_min) >> - LG_SUBPAGE); - custom_small_size2bin[i] = binind; - } - - small_size2bin = custom_small_size2bin; -#ifdef JEMALLOC_DEBUG - small_size2bin_validate(); -#endif - return (false); -} - -bool +void arena_boot(void) { size_t header_size; unsigned i; - /* Set variables according to the value of opt_lg_[qc]space_max. */ - qspace_max = (1U << opt_lg_qspace_max); - cspace_min = CACHELINE_CEILING(qspace_max); - if (cspace_min == qspace_max) - cspace_min += CACHELINE; - cspace_max = (1U << opt_lg_cspace_max); - sspace_min = SUBPAGE_CEILING(cspace_max); - if (sspace_min == cspace_max) - sspace_min += SUBPAGE; - assert(sspace_min < PAGE_SIZE); - sspace_max = PAGE_SIZE - SUBPAGE; - -#ifdef JEMALLOC_TINY - assert(LG_QUANTUM >= LG_TINY_MIN); -#endif - assert(ntbins <= LG_QUANTUM); - nqbins = qspace_max >> LG_QUANTUM; - ncbins = ((cspace_max - cspace_min) >> LG_CACHELINE) + 1; - nsbins = ((sspace_max - sspace_min) >> LG_SUBPAGE) + 1; - nbins = ntbins + nqbins + ncbins + nsbins; - - /* - * The small_size2bin lookup table uses uint8_t to encode each bin - * index, so we cannot support more than 256 small size classes. This - * limit is difficult to exceed (not even possible with 16B quantum and - * 4KiB pages), and such configurations are impractical, but - * nonetheless we need to protect against this case in order to avoid - * undefined behavior. - * - * Further constrain nbins to 255 if prof_promote is true, since all - * small size classes, plus a "not small" size class must be stored in - * 8 bits of arena_chunk_map_t's bits field. - */ -#ifdef JEMALLOC_PROF - if (opt_prof && prof_promote) { - if (nbins > 255) { - char line_buf[UMAX2S_BUFSIZE]; - malloc_write("<jemalloc>: Too many small size classes ("); - malloc_write(u2s(nbins, 10, line_buf)); - malloc_write(" > max 255)\n"); - abort(); - } - } else -#endif - if (nbins > 256) { - char line_buf[UMAX2S_BUFSIZE]; - malloc_write("<jemalloc>: Too many small size classes ("); - malloc_write(u2s(nbins, 10, line_buf)); - malloc_write(" > max 256)\n"); - abort(); - } - - if (small_size2bin_init()) - return (true); - /* * Compute the header size such that it is large enough to contain the * page map. The page map is biased to omit entries for the header @@ -2562,14 +2322,44 @@ arena_boot(void) */ map_bias = 0; for (i = 0; i < 3; i++) { - header_size = offsetof(arena_chunk_t, map) - + (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias)); - map_bias = (header_size >> PAGE_SHIFT) + ((header_size & - PAGE_MASK) != 0); + header_size = offsetof(arena_chunk_t, map) + + (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias)); + map_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK) + != 0); } assert(map_bias > 0); - arena_maxclass = chunksize - (map_bias << PAGE_SHIFT); + arena_maxclass = chunksize - (map_bias << LG_PAGE); - return (false); + bin_info_init(); +} + +void +arena_prefork(arena_t *arena) +{ + unsigned i; + + malloc_mutex_prefork(&arena->lock); + for (i = 0; i < NBINS; i++) + malloc_mutex_prefork(&arena->bins[i].lock); +} + +void +arena_postfork_parent(arena_t *arena) +{ + unsigned i; + + for (i = 0; i < NBINS; i++) + malloc_mutex_postfork_parent(&arena->bins[i].lock); + malloc_mutex_postfork_parent(&arena->lock); +} + +void +arena_postfork_child(arena_t *arena) +{ + unsigned i; + + for (i = 0; i < NBINS; i++) + malloc_mutex_postfork_child(&arena->bins[i].lock); + malloc_mutex_postfork_child(&arena->lock); } diff --git a/dep/jemalloc/src/atomic.c b/dep/jemalloc/src/atomic.c new file mode 100644 index 00000000000..77ee313113b --- /dev/null +++ b/dep/jemalloc/src/atomic.c @@ -0,0 +1,2 @@ +#define JEMALLOC_ATOMIC_C_ +#include "jemalloc/internal/jemalloc_internal.h" diff --git a/dep/jemalloc/src/base.c b/dep/jemalloc/src/base.c index cc85e8494ec..4e62e8fa918 100644 --- a/dep/jemalloc/src/base.c +++ b/dep/jemalloc/src/base.c @@ -4,7 +4,7 @@ /******************************************************************************/ /* Data. */ -malloc_mutex_t base_mtx; +static malloc_mutex_t base_mtx; /* * Current pages that are being used for internal memory allocations. These @@ -32,7 +32,8 @@ base_pages_alloc(size_t minsize) assert(minsize != 0); csize = CHUNK_CEILING(minsize); zero = false; - base_pages = chunk_alloc(csize, true, &zero); + base_pages = chunk_alloc(csize, chunksize, true, &zero, + chunk_dss_prec_get()); if (base_pages == NULL) return (true); base_next_addr = base_pages; @@ -62,6 +63,18 @@ base_alloc(size_t size) ret = base_next_addr; base_next_addr = (void *)((uintptr_t)base_next_addr + csize); malloc_mutex_unlock(&base_mtx); + VALGRIND_MAKE_MEM_UNDEFINED(ret, csize); + + return (ret); +} + +void * +base_calloc(size_t number, size_t size) +{ + void *ret = base_alloc(number * size); + + if (ret != NULL) + memset(ret, 0, number * size); return (ret); } @@ -76,6 +89,7 @@ base_node_alloc(void) ret = base_nodes; base_nodes = *(extent_node_t **)ret; malloc_mutex_unlock(&base_mtx); + VALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t)); } else { malloc_mutex_unlock(&base_mtx); ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); @@ -88,6 +102,7 @@ void base_node_dealloc(extent_node_t *node) { + VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); malloc_mutex_lock(&base_mtx); *(extent_node_t **)node = base_nodes; base_nodes = node; @@ -104,3 +119,24 @@ base_boot(void) return (false); } + +void +base_prefork(void) +{ + + malloc_mutex_prefork(&base_mtx); +} + +void +base_postfork_parent(void) +{ + + malloc_mutex_postfork_parent(&base_mtx); +} + +void +base_postfork_child(void) +{ + + malloc_mutex_postfork_child(&base_mtx); +} diff --git a/dep/jemalloc/src/bitmap.c b/dep/jemalloc/src/bitmap.c new file mode 100644 index 00000000000..b47e2629093 --- /dev/null +++ b/dep/jemalloc/src/bitmap.c @@ -0,0 +1,90 @@ +#define JEMALLOC_BITMAP_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static size_t bits2groups(size_t nbits); + +/******************************************************************************/ + +static size_t +bits2groups(size_t nbits) +{ + + return ((nbits >> LG_BITMAP_GROUP_NBITS) + + !!(nbits & BITMAP_GROUP_NBITS_MASK)); +} + +void +bitmap_info_init(bitmap_info_t *binfo, size_t nbits) +{ + unsigned i; + size_t group_count; + + assert(nbits > 0); + assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS)); + + /* + * Compute the number of groups necessary to store nbits bits, and + * progressively work upward through the levels until reaching a level + * that requires only one group. + */ + binfo->levels[0].group_offset = 0; + group_count = bits2groups(nbits); + for (i = 1; group_count > 1; i++) { + assert(i < BITMAP_MAX_LEVELS); + binfo->levels[i].group_offset = binfo->levels[i-1].group_offset + + group_count; + group_count = bits2groups(group_count); + } + binfo->levels[i].group_offset = binfo->levels[i-1].group_offset + + group_count; + binfo->nlevels = i; + binfo->nbits = nbits; +} + +size_t +bitmap_info_ngroups(const bitmap_info_t *binfo) +{ + + return (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP); +} + +size_t +bitmap_size(size_t nbits) +{ + bitmap_info_t binfo; + + bitmap_info_init(&binfo, nbits); + return (bitmap_info_ngroups(&binfo)); +} + +void +bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo) +{ + size_t extra; + unsigned i; + + /* + * Bits are actually inverted with regard to the external bitmap + * interface, so the bitmap starts out with all 1 bits, except for + * trailing unused bits (if any). Note that each group uses bit 0 to + * correspond to the first logical bit in the group, so extra bits + * are the most significant bits of the last group. + */ + memset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset << + LG_SIZEOF_BITMAP); + extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) + & BITMAP_GROUP_NBITS_MASK; + if (extra != 0) + bitmap[binfo->levels[1].group_offset - 1] >>= extra; + for (i = 1; i < binfo->nlevels; i++) { + size_t group_count = binfo->levels[i].group_offset - + binfo->levels[i-1].group_offset; + extra = (BITMAP_GROUP_NBITS - (group_count & + BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK; + if (extra != 0) + bitmap[binfo->levels[i+1].group_offset - 1] >>= extra; + } +} diff --git a/dep/jemalloc/src/chunk.c b/dep/jemalloc/src/chunk.c index 301519e8042..044f76be96c 100644 --- a/dep/jemalloc/src/chunk.c +++ b/dep/jemalloc/src/chunk.c @@ -4,19 +4,24 @@ /******************************************************************************/ /* Data. */ -size_t opt_lg_chunk = LG_CHUNK_DEFAULT; -#ifdef JEMALLOC_SWAP -bool opt_overcommit = true; -#endif +const char *opt_dss = DSS_DEFAULT; +size_t opt_lg_chunk = LG_CHUNK_DEFAULT; -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) malloc_mutex_t chunks_mtx; chunk_stats_t stats_chunks; -#endif -#ifdef JEMALLOC_IVSALLOC +/* + * Trees of chunks that were previously allocated (trees differ only in node + * ordering). These are used when allocating chunks, in an attempt to re-use + * address space. Depending on function, different tree orderings are needed, + * which is why there are two trees with the same contents. + */ +static extent_tree_t chunks_szad_mmap; +static extent_tree_t chunks_ad_mmap; +static extent_tree_t chunks_szad_dss; +static extent_tree_t chunks_ad_dss; + rtree_t *chunks_rtree; -#endif /* Various chunk-related settings. */ size_t chunksize; @@ -26,6 +31,109 @@ size_t map_bias; size_t arena_maxclass; /* Max size class for arenas. */ /******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static void *chunk_recycle(extent_tree_t *chunks_szad, + extent_tree_t *chunks_ad, size_t size, size_t alignment, bool base, + bool *zero); +static void chunk_record(extent_tree_t *chunks_szad, + extent_tree_t *chunks_ad, void *chunk, size_t size); + +/******************************************************************************/ + +static void * +chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size, + size_t alignment, bool base, bool *zero) +{ + void *ret; + extent_node_t *node; + extent_node_t key; + size_t alloc_size, leadsize, trailsize; + bool zeroed; + + if (base) { + /* + * This function may need to call base_node_{,de}alloc(), but + * the current chunk allocation request is on behalf of the + * base allocator. Avoid deadlock (and if that weren't an + * issue, potential for infinite recursion) by returning NULL. + */ + return (NULL); + } + + alloc_size = size + alignment - chunksize; + /* Beware size_t wrap-around. */ + if (alloc_size < size) + return (NULL); + key.addr = NULL; + key.size = alloc_size; + malloc_mutex_lock(&chunks_mtx); + node = extent_tree_szad_nsearch(chunks_szad, &key); + if (node == NULL) { + malloc_mutex_unlock(&chunks_mtx); + return (NULL); + } + leadsize = ALIGNMENT_CEILING((uintptr_t)node->addr, alignment) - + (uintptr_t)node->addr; + assert(node->size >= leadsize + size); + trailsize = node->size - leadsize - size; + ret = (void *)((uintptr_t)node->addr + leadsize); + zeroed = node->zeroed; + if (zeroed) + *zero = true; + /* Remove node from the tree. */ + extent_tree_szad_remove(chunks_szad, node); + extent_tree_ad_remove(chunks_ad, node); + if (leadsize != 0) { + /* Insert the leading space as a smaller chunk. */ + node->size = leadsize; + extent_tree_szad_insert(chunks_szad, node); + extent_tree_ad_insert(chunks_ad, node); + node = NULL; + } + if (trailsize != 0) { + /* Insert the trailing space as a smaller chunk. */ + if (node == NULL) { + /* + * An additional node is required, but + * base_node_alloc() can cause a new base chunk to be + * allocated. Drop chunks_mtx in order to avoid + * deadlock, and if node allocation fails, deallocate + * the result before returning an error. + */ + malloc_mutex_unlock(&chunks_mtx); + node = base_node_alloc(); + if (node == NULL) { + chunk_dealloc(ret, size, true); + return (NULL); + } + malloc_mutex_lock(&chunks_mtx); + } + node->addr = (void *)((uintptr_t)(ret) + size); + node->size = trailsize; + node->zeroed = zeroed; + extent_tree_szad_insert(chunks_szad, node); + extent_tree_ad_insert(chunks_ad, node); + node = NULL; + } + malloc_mutex_unlock(&chunks_mtx); + + if (node != NULL) + base_node_dealloc(node); + if (*zero) { + if (zeroed == false) + memset(ret, 0, size); + else if (config_debug) { + size_t i; + size_t *p = (size_t *)(uintptr_t)ret; + + VALGRIND_MAKE_MEM_DEFINED(ret, size); + for (i = 0; i < size / sizeof(size_t); i++) + assert(p[i] == 0); + } + } + return (ret); +} /* * If the caller specifies (*zero == false), it is still possible to receive @@ -34,81 +142,167 @@ size_t arena_maxclass; /* Max size class for arenas. */ * advantage of them if they are returned. */ void * -chunk_alloc(size_t size, bool base, bool *zero) +chunk_alloc(size_t size, size_t alignment, bool base, bool *zero, + dss_prec_t dss_prec) { void *ret; assert(size != 0); assert((size & chunksize_mask) == 0); + assert(alignment != 0); + assert((alignment & chunksize_mask) == 0); -#ifdef JEMALLOC_SWAP - if (swap_enabled) { - ret = chunk_alloc_swap(size, zero); - if (ret != NULL) - goto RETURN; + /* "primary" dss. */ + if (config_dss && dss_prec == dss_prec_primary) { + if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size, + alignment, base, zero)) != NULL) + goto label_return; + if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL) + goto label_return; } - - if (swap_enabled == false || opt_overcommit) { -#endif -#ifdef JEMALLOC_DSS - ret = chunk_alloc_dss(size, zero); - if (ret != NULL) - goto RETURN; -#endif - ret = chunk_alloc_mmap(size); - if (ret != NULL) { - *zero = true; - goto RETURN; - } -#ifdef JEMALLOC_SWAP + /* mmap. */ + if ((ret = chunk_recycle(&chunks_szad_mmap, &chunks_ad_mmap, size, + alignment, base, zero)) != NULL) + goto label_return; + if ((ret = chunk_alloc_mmap(size, alignment, zero)) != NULL) + goto label_return; + /* "secondary" dss. */ + if (config_dss && dss_prec == dss_prec_secondary) { + if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size, + alignment, base, zero)) != NULL) + goto label_return; + if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL) + goto label_return; } -#endif /* All strategies for allocation failed. */ ret = NULL; -RETURN: -#ifdef JEMALLOC_IVSALLOC - if (base == false && ret != NULL) { - if (rtree_set(chunks_rtree, (uintptr_t)ret, ret)) { - chunk_dealloc(ret, size); - return (NULL); - } - } -#endif -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) +label_return: if (ret != NULL) { -# ifdef JEMALLOC_PROF - bool gdump; -# endif - malloc_mutex_lock(&chunks_mtx); -# ifdef JEMALLOC_STATS - stats_chunks.nchunks += (size / chunksize); -# endif - stats_chunks.curchunks += (size / chunksize); - if (stats_chunks.curchunks > stats_chunks.highchunks) { - stats_chunks.highchunks = stats_chunks.curchunks; -# ifdef JEMALLOC_PROF - gdump = true; -# endif + if (config_ivsalloc && base == false) { + if (rtree_set(chunks_rtree, (uintptr_t)ret, ret)) { + chunk_dealloc(ret, size, true); + return (NULL); + } } -# ifdef JEMALLOC_PROF - else - gdump = false; -# endif - malloc_mutex_unlock(&chunks_mtx); -# ifdef JEMALLOC_PROF - if (opt_prof && opt_prof_gdump && gdump) - prof_gdump(); -# endif + if (config_stats || config_prof) { + bool gdump; + malloc_mutex_lock(&chunks_mtx); + if (config_stats) + stats_chunks.nchunks += (size / chunksize); + stats_chunks.curchunks += (size / chunksize); + if (stats_chunks.curchunks > stats_chunks.highchunks) { + stats_chunks.highchunks = + stats_chunks.curchunks; + if (config_prof) + gdump = true; + } else if (config_prof) + gdump = false; + malloc_mutex_unlock(&chunks_mtx); + if (config_prof && opt_prof && opt_prof_gdump && gdump) + prof_gdump(); + } + if (config_valgrind) + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); } -#endif - assert(CHUNK_ADDR2BASE(ret) == ret); return (ret); } +static void +chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, + size_t size) +{ + bool unzeroed; + extent_node_t *xnode, *node, *prev, key; + + unzeroed = pages_purge(chunk, size); + VALGRIND_MAKE_MEM_NOACCESS(chunk, size); + + /* + * Allocate a node before acquiring chunks_mtx even though it might not + * be needed, because base_node_alloc() may cause a new base chunk to + * be allocated, which could cause deadlock if chunks_mtx were already + * held. + */ + xnode = base_node_alloc(); + + malloc_mutex_lock(&chunks_mtx); + key.addr = (void *)((uintptr_t)chunk + size); + node = extent_tree_ad_nsearch(chunks_ad, &key); + /* Try to coalesce forward. */ + if (node != NULL && node->addr == key.addr) { + /* + * Coalesce chunk with the following address range. This does + * not change the position within chunks_ad, so only + * remove/insert from/into chunks_szad. + */ + extent_tree_szad_remove(chunks_szad, node); + node->addr = chunk; + node->size += size; + node->zeroed = (node->zeroed && (unzeroed == false)); + extent_tree_szad_insert(chunks_szad, node); + if (xnode != NULL) + base_node_dealloc(xnode); + } else { + /* Coalescing forward failed, so insert a new node. */ + if (xnode == NULL) { + /* + * base_node_alloc() failed, which is an exceedingly + * unlikely failure. Leak chunk; its pages have + * already been purged, so this is only a virtual + * memory leak. + */ + malloc_mutex_unlock(&chunks_mtx); + return; + } + node = xnode; + node->addr = chunk; + node->size = size; + node->zeroed = (unzeroed == false); + extent_tree_ad_insert(chunks_ad, node); + extent_tree_szad_insert(chunks_szad, node); + } + + /* Try to coalesce backward. */ + prev = extent_tree_ad_prev(chunks_ad, node); + if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == + chunk) { + /* + * Coalesce chunk with the previous address range. This does + * not change the position within chunks_ad, so only + * remove/insert node from/into chunks_szad. + */ + extent_tree_szad_remove(chunks_szad, prev); + extent_tree_ad_remove(chunks_ad, prev); + + extent_tree_szad_remove(chunks_szad, node); + node->addr = prev->addr; + node->size += prev->size; + node->zeroed = (node->zeroed && prev->zeroed); + extent_tree_szad_insert(chunks_szad, node); + + base_node_dealloc(prev); + } + malloc_mutex_unlock(&chunks_mtx); +} + void -chunk_dealloc(void *chunk, size_t size) +chunk_unmap(void *chunk, size_t size) +{ + assert(chunk != NULL); + assert(CHUNK_ADDR2BASE(chunk) == chunk); + assert(size != 0); + assert((size & chunksize_mask) == 0); + + if (config_dss && chunk_in_dss(chunk)) + chunk_record(&chunks_szad_dss, &chunks_ad_dss, chunk, size); + else if (chunk_dealloc_mmap(chunk, size)) + chunk_record(&chunks_szad_mmap, &chunks_ad_mmap, chunk, size); +} + +void +chunk_dealloc(void *chunk, size_t size, bool unmap) { assert(chunk != NULL); @@ -116,24 +310,17 @@ chunk_dealloc(void *chunk, size_t size) assert(size != 0); assert((size & chunksize_mask) == 0); -#ifdef JEMALLOC_IVSALLOC - rtree_set(chunks_rtree, (uintptr_t)chunk, NULL); -#endif -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - malloc_mutex_lock(&chunks_mtx); - stats_chunks.curchunks -= (size / chunksize); - malloc_mutex_unlock(&chunks_mtx); -#endif - -#ifdef JEMALLOC_SWAP - if (swap_enabled && chunk_dealloc_swap(chunk, size) == false) - return; -#endif -#ifdef JEMALLOC_DSS - if (chunk_dealloc_dss(chunk, size) == false) - return; -#endif - chunk_dealloc_mmap(chunk, size); + if (config_ivsalloc) + rtree_set(chunks_rtree, (uintptr_t)chunk, NULL); + if (config_stats || config_prof) { + malloc_mutex_lock(&chunks_mtx); + assert(stats_chunks.curchunks >= (size / chunksize)); + stats_chunks.curchunks -= (size / chunksize); + malloc_mutex_unlock(&chunks_mtx); + } + + if (unmap) + chunk_unmap(chunk, size); } bool @@ -142,30 +329,57 @@ chunk_boot(void) /* Set variables according to the value of opt_lg_chunk. */ chunksize = (ZU(1) << opt_lg_chunk); - assert(chunksize >= PAGE_SIZE); + assert(chunksize >= PAGE); chunksize_mask = chunksize - 1; - chunk_npages = (chunksize >> PAGE_SHIFT); + chunk_npages = (chunksize >> LG_PAGE); -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - if (malloc_mutex_init(&chunks_mtx)) - return (true); - memset(&stats_chunks, 0, sizeof(chunk_stats_t)); -#endif -#ifdef JEMALLOC_SWAP - if (chunk_swap_boot()) - return (true); -#endif - if (chunk_mmap_boot()) - return (true); -#ifdef JEMALLOC_DSS - if (chunk_dss_boot()) - return (true); -#endif -#ifdef JEMALLOC_IVSALLOC - chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - opt_lg_chunk); - if (chunks_rtree == NULL) + if (config_stats || config_prof) { + if (malloc_mutex_init(&chunks_mtx)) + return (true); + memset(&stats_chunks, 0, sizeof(chunk_stats_t)); + } + if (config_dss && chunk_dss_boot()) return (true); -#endif + extent_tree_szad_new(&chunks_szad_mmap); + extent_tree_ad_new(&chunks_ad_mmap); + extent_tree_szad_new(&chunks_szad_dss); + extent_tree_ad_new(&chunks_ad_dss); + if (config_ivsalloc) { + chunks_rtree = rtree_new((ZU(1) << (LG_SIZEOF_PTR+3)) - + opt_lg_chunk); + if (chunks_rtree == NULL) + return (true); + } return (false); } + +void +chunk_prefork(void) +{ + + malloc_mutex_lock(&chunks_mtx); + if (config_ivsalloc) + rtree_prefork(chunks_rtree); + chunk_dss_prefork(); +} + +void +chunk_postfork_parent(void) +{ + + chunk_dss_postfork_parent(); + if (config_ivsalloc) + rtree_postfork_parent(chunks_rtree); + malloc_mutex_postfork_parent(&chunks_mtx); +} + +void +chunk_postfork_child(void) +{ + + chunk_dss_postfork_child(); + if (config_ivsalloc) + rtree_postfork_child(chunks_rtree); + malloc_mutex_postfork_child(&chunks_mtx); +} diff --git a/dep/jemalloc/src/chunk_dss.c b/dep/jemalloc/src/chunk_dss.c index 5c0e290e441..24781cc52dc 100644 --- a/dep/jemalloc/src/chunk_dss.c +++ b/dep/jemalloc/src/chunk_dss.c @@ -1,82 +1,77 @@ #define JEMALLOC_CHUNK_DSS_C_ #include "jemalloc/internal/jemalloc_internal.h" -#ifdef JEMALLOC_DSS /******************************************************************************/ /* Data. */ -malloc_mutex_t dss_mtx; +const char *dss_prec_names[] = { + "disabled", + "primary", + "secondary", + "N/A" +}; -/* Base address of the DSS. */ -static void *dss_base; -/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */ -static void *dss_prev; -/* Current upper limit on DSS addresses. */ -static void *dss_max; +/* Current dss precedence default, used when creating new arenas. */ +static dss_prec_t dss_prec_default = DSS_PREC_DEFAULT; /* - * Trees of chunks that were previously allocated (trees differ only in node - * ordering). These are used when allocating chunks, in an attempt to re-use - * address space. Depending on function, different tree orderings are needed, - * which is why there are two trees with the same contents. + * Protects sbrk() calls. This avoids malloc races among threads, though it + * does not protect against races with threads that call sbrk() directly. */ -static extent_tree_t dss_chunks_szad; -static extent_tree_t dss_chunks_ad; - -/******************************************************************************/ -/* Function prototypes for non-inline static functions. */ +static malloc_mutex_t dss_mtx; -static void *chunk_recycle_dss(size_t size, bool *zero); -static extent_node_t *chunk_dealloc_dss_record(void *chunk, size_t size); +/* Base address of the DSS. */ +static void *dss_base; +/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */ +static void *dss_prev; +/* Current upper limit on DSS addresses. */ +static void *dss_max; /******************************************************************************/ +#ifndef JEMALLOC_HAVE_SBRK static void * -chunk_recycle_dss(size_t size, bool *zero) +sbrk(intptr_t increment) +{ + + not_implemented(); + + return (NULL); +} +#endif + +dss_prec_t +chunk_dss_prec_get(void) { - extent_node_t *node, key; + dss_prec_t ret; - key.addr = NULL; - key.size = size; + if (config_dss == false) + return (dss_prec_disabled); malloc_mutex_lock(&dss_mtx); - node = extent_tree_szad_nsearch(&dss_chunks_szad, &key); - if (node != NULL) { - void *ret = node->addr; - - /* Remove node from the tree. */ - extent_tree_szad_remove(&dss_chunks_szad, node); - if (node->size == size) { - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } else { - /* - * Insert the remainder of node's address range as a - * smaller chunk. Its position within dss_chunks_ad - * does not change. - */ - assert(node->size > size); - node->addr = (void *)((uintptr_t)node->addr + size); - node->size -= size; - extent_tree_szad_insert(&dss_chunks_szad, node); - } - malloc_mutex_unlock(&dss_mtx); - - if (*zero) - memset(ret, 0, size); - return (ret); - } + ret = dss_prec_default; malloc_mutex_unlock(&dss_mtx); + return (ret); +} - return (NULL); +bool +chunk_dss_prec_set(dss_prec_t dss_prec) +{ + + if (config_dss == false) + return (true); + malloc_mutex_lock(&dss_mtx); + dss_prec_default = dss_prec; + malloc_mutex_unlock(&dss_mtx); + return (false); } void * -chunk_alloc_dss(size_t size, bool *zero) +chunk_alloc_dss(size_t size, size_t alignment, bool *zero) { void *ret; - ret = chunk_recycle_dss(size, zero); - if (ret != NULL) - return (ret); + cassert(config_dss); + assert(size > 0 && (size & chunksize_mask) == 0); + assert(alignment > 0 && (alignment & chunksize_mask) == 0); /* * sbrk() uses a signed increment argument, so take care not to @@ -87,6 +82,8 @@ chunk_alloc_dss(size_t size, bool *zero) malloc_mutex_lock(&dss_mtx); if (dss_prev != (void *)-1) { + size_t gap_size, cpad_size; + void *cpad, *dss_next; intptr_t incr; /* @@ -97,26 +94,40 @@ chunk_alloc_dss(size_t size, bool *zero) do { /* Get the current end of the DSS. */ dss_max = sbrk(0); - /* * Calculate how much padding is necessary to * chunk-align the end of the DSS. */ - incr = (intptr_t)size - - (intptr_t)CHUNK_ADDR2OFFSET(dss_max); - if (incr == (intptr_t)size) - ret = dss_max; - else { - ret = (void *)((intptr_t)dss_max + incr); - incr += size; + gap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) & + chunksize_mask; + /* + * Compute how much chunk-aligned pad space (if any) is + * necessary to satisfy alignment. This space can be + * recycled for later use. + */ + cpad = (void *)((uintptr_t)dss_max + gap_size); + ret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max, + alignment); + cpad_size = (uintptr_t)ret - (uintptr_t)cpad; + dss_next = (void *)((uintptr_t)ret + size); + if ((uintptr_t)ret < (uintptr_t)dss_max || + (uintptr_t)dss_next < (uintptr_t)dss_max) { + /* Wrap-around. */ + malloc_mutex_unlock(&dss_mtx); + return (NULL); } - + incr = gap_size + cpad_size + size; dss_prev = sbrk(incr); if (dss_prev == dss_max) { /* Success. */ - dss_max = (void *)((intptr_t)dss_prev + incr); + dss_max = dss_next; malloc_mutex_unlock(&dss_mtx); - *zero = true; + if (cpad_size != 0) + chunk_unmap(cpad, cpad_size); + if (*zero) { + VALGRIND_MAKE_MEM_UNDEFINED(ret, size); + memset(ret, 0, size); + } return (ret); } } while (dss_prev != (void *)-1); @@ -126,84 +137,13 @@ chunk_alloc_dss(size_t size, bool *zero) return (NULL); } -static extent_node_t * -chunk_dealloc_dss_record(void *chunk, size_t size) -{ - extent_node_t *xnode, *node, *prev, key; - - xnode = NULL; - while (true) { - key.addr = (void *)((uintptr_t)chunk + size); - node = extent_tree_ad_nsearch(&dss_chunks_ad, &key); - /* Try to coalesce forward. */ - if (node != NULL && node->addr == key.addr) { - /* - * Coalesce chunk with the following address range. - * This does not change the position within - * dss_chunks_ad, so only remove/insert from/into - * dss_chunks_szad. - */ - extent_tree_szad_remove(&dss_chunks_szad, node); - node->addr = chunk; - node->size += size; - extent_tree_szad_insert(&dss_chunks_szad, node); - break; - } else if (xnode == NULL) { - /* - * It is possible that base_node_alloc() will cause a - * new base chunk to be allocated, so take care not to - * deadlock on dss_mtx, and recover if another thread - * deallocates an adjacent chunk while this one is busy - * allocating xnode. - */ - malloc_mutex_unlock(&dss_mtx); - xnode = base_node_alloc(); - malloc_mutex_lock(&dss_mtx); - if (xnode == NULL) - return (NULL); - } else { - /* Coalescing forward failed, so insert a new node. */ - node = xnode; - xnode = NULL; - node->addr = chunk; - node->size = size; - extent_tree_ad_insert(&dss_chunks_ad, node); - extent_tree_szad_insert(&dss_chunks_szad, node); - break; - } - } - /* Discard xnode if it ended up unused do to a race. */ - if (xnode != NULL) - base_node_dealloc(xnode); - - /* Try to coalesce backward. */ - prev = extent_tree_ad_prev(&dss_chunks_ad, node); - if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == - chunk) { - /* - * Coalesce chunk with the previous address range. This does - * not change the position within dss_chunks_ad, so only - * remove/insert node from/into dss_chunks_szad. - */ - extent_tree_szad_remove(&dss_chunks_szad, prev); - extent_tree_ad_remove(&dss_chunks_ad, prev); - - extent_tree_szad_remove(&dss_chunks_szad, node); - node->addr = prev->addr; - node->size += prev->size; - extent_tree_szad_insert(&dss_chunks_szad, node); - - base_node_dealloc(prev); - } - - return (node); -} - bool chunk_in_dss(void *chunk) { bool ret; + cassert(config_dss); + malloc_mutex_lock(&dss_mtx); if ((uintptr_t)chunk >= (uintptr_t)dss_base && (uintptr_t)chunk < (uintptr_t)dss_max) @@ -216,69 +156,42 @@ chunk_in_dss(void *chunk) } bool -chunk_dealloc_dss(void *chunk, size_t size) +chunk_dss_boot(void) { - bool ret; - malloc_mutex_lock(&dss_mtx); - if ((uintptr_t)chunk >= (uintptr_t)dss_base - && (uintptr_t)chunk < (uintptr_t)dss_max) { - extent_node_t *node; + cassert(config_dss); - /* Try to coalesce with other unused chunks. */ - node = chunk_dealloc_dss_record(chunk, size); - if (node != NULL) { - chunk = node->addr; - size = node->size; - } - - /* Get the current end of the DSS. */ - dss_max = sbrk(0); + if (malloc_mutex_init(&dss_mtx)) + return (true); + dss_base = sbrk(0); + dss_prev = dss_base; + dss_max = dss_base; - /* - * Try to shrink the DSS if this chunk is at the end of the - * DSS. The sbrk() call here is subject to a race condition - * with threads that use brk(2) or sbrk(2) directly, but the - * alternative would be to leak memory for the sake of poorly - * designed multi-threaded programs. - */ - if ((void *)((uintptr_t)chunk + size) == dss_max - && (dss_prev = sbrk(-(intptr_t)size)) == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev - (intptr_t)size); - - if (node != NULL) { - extent_tree_szad_remove(&dss_chunks_szad, node); - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } - } else - madvise(chunk, size, MADV_DONTNEED); + return (false); +} - ret = false; - goto RETURN; - } +void +chunk_dss_prefork(void) +{ - ret = true; -RETURN: - malloc_mutex_unlock(&dss_mtx); - return (ret); + if (config_dss) + malloc_mutex_prefork(&dss_mtx); } -bool -chunk_dss_boot(void) +void +chunk_dss_postfork_parent(void) { - if (malloc_mutex_init(&dss_mtx)) - return (true); - dss_base = sbrk(0); - dss_prev = dss_base; - dss_max = dss_base; - extent_tree_szad_new(&dss_chunks_szad); - extent_tree_ad_new(&dss_chunks_ad); + if (config_dss) + malloc_mutex_postfork_parent(&dss_mtx); +} - return (false); +void +chunk_dss_postfork_child(void) +{ + + if (config_dss) + malloc_mutex_postfork_child(&dss_mtx); } /******************************************************************************/ -#endif /* JEMALLOC_DSS */ diff --git a/dep/jemalloc/src/chunk_mmap.c b/dep/jemalloc/src/chunk_mmap.c index bc367559774..8a42e75915f 100644 --- a/dep/jemalloc/src/chunk_mmap.c +++ b/dep/jemalloc/src/chunk_mmap.c @@ -2,53 +2,36 @@ #include "jemalloc/internal/jemalloc_internal.h" /******************************************************************************/ -/* Data. */ - -/* - * Used by chunk_alloc_mmap() to decide whether to attempt the fast path and - * potentially avoid some system calls. - */ -#ifndef NO_TLS -static __thread bool mmap_unaligned_tls - JEMALLOC_ATTR(tls_model("initial-exec")); -#define MMAP_UNALIGNED_GET() mmap_unaligned_tls -#define MMAP_UNALIGNED_SET(v) do { \ - mmap_unaligned_tls = (v); \ -} while (0) -#else -static pthread_key_t mmap_unaligned_tsd; -#define MMAP_UNALIGNED_GET() ((bool)pthread_getspecific(mmap_unaligned_tsd)) -#define MMAP_UNALIGNED_SET(v) do { \ - pthread_setspecific(mmap_unaligned_tsd, (void *)(v)); \ -} while (0) -#endif - -/******************************************************************************/ /* Function prototypes for non-inline static functions. */ -static void *pages_map(void *addr, size_t size, bool noreserve); +static void *pages_map(void *addr, size_t size); static void pages_unmap(void *addr, size_t size); -static void *chunk_alloc_mmap_slow(size_t size, bool unaligned, - bool noreserve); -static void *chunk_alloc_mmap_internal(size_t size, bool noreserve); +static void *chunk_alloc_mmap_slow(size_t size, size_t alignment, + bool *zero); /******************************************************************************/ static void * -pages_map(void *addr, size_t size, bool noreserve) +pages_map(void *addr, size_t size) { void *ret; + assert(size != 0); + +#ifdef _WIN32 + /* + * If VirtualAlloc can't allocate at the given address when one is + * given, it fails and returns NULL. + */ + ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, + PAGE_READWRITE); +#else /* * We don't use MAP_FIXED here, because it can cause the *replacement* * of existing mappings, and we only want to create new mappings. */ - int flags = MAP_PRIVATE | MAP_ANON; -#ifdef MAP_NORESERVE - if (noreserve) - flags |= MAP_NORESERVE; -#endif - ret = mmap(addr, size, PROT_READ | PROT_WRITE, flags, -1, 0); + ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, + -1, 0); assert(ret != NULL); if (ret == MAP_FAILED) @@ -60,16 +43,15 @@ pages_map(void *addr, size_t size, bool noreserve) if (munmap(ret, size) == -1) { char buf[BUFERROR_BUF]; - buferror(errno, buf, sizeof(buf)); - malloc_write("<jemalloc>: Error in munmap(): "); - malloc_write(buf); - malloc_write("\n"); + buferror(buf, sizeof(buf)); + malloc_printf("<jemalloc: Error in munmap(): %s\n", + buf); if (opt_abort) abort(); } ret = NULL; } - +#endif assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL && ret == addr)); return (ret); @@ -79,159 +61,150 @@ static void pages_unmap(void *addr, size_t size) { - if (munmap(addr, size) == -1) { +#ifdef _WIN32 + if (VirtualFree(addr, 0, MEM_RELEASE) == 0) +#else + if (munmap(addr, size) == -1) +#endif + { char buf[BUFERROR_BUF]; - buferror(errno, buf, sizeof(buf)); - malloc_write("<jemalloc>: Error in munmap(): "); - malloc_write(buf); - malloc_write("\n"); + buferror(buf, sizeof(buf)); + malloc_printf("<jemalloc>: Error in " +#ifdef _WIN32 + "VirtualFree" +#else + "munmap" +#endif + "(): %s\n", buf); if (opt_abort) abort(); } } static void * -chunk_alloc_mmap_slow(size_t size, bool unaligned, bool noreserve) +pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size) { - void *ret; - size_t offset; - - /* Beware size_t wrap-around. */ - if (size + chunksize <= size) + void *ret = (void *)((uintptr_t)addr + leadsize); + + assert(alloc_size >= leadsize + size); +#ifdef _WIN32 + { + void *new_addr; + + pages_unmap(addr, alloc_size); + new_addr = pages_map(ret, size); + if (new_addr == ret) + return (ret); + if (new_addr) + pages_unmap(new_addr, size); return (NULL); + } +#else + { + size_t trailsize = alloc_size - leadsize - size; + + if (leadsize != 0) + pages_unmap(addr, leadsize); + if (trailsize != 0) + pages_unmap((void *)((uintptr_t)ret + size), trailsize); + return (ret); + } +#endif +} - ret = pages_map(NULL, size + chunksize, noreserve); - if (ret == NULL) - return (NULL); +bool +pages_purge(void *addr, size_t length) +{ + bool unzeroed; - /* Clean up unneeded leading/trailing space. */ - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - /* Note that mmap() returned an unaligned mapping. */ - unaligned = true; - - /* Leading space. */ - pages_unmap(ret, chunksize - offset); - - ret = (void *)((uintptr_t)ret + - (chunksize - offset)); - - /* Trailing space. */ - pages_unmap((void *)((uintptr_t)ret + size), - offset); - } else { - /* Trailing space only. */ - pages_unmap((void *)((uintptr_t)ret + size), - chunksize); - } +#ifdef _WIN32 + VirtualAlloc(addr, length, MEM_RESET, PAGE_READWRITE); + unzeroed = true; +#else +# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED +# define JEMALLOC_MADV_PURGE MADV_DONTNEED +# define JEMALLOC_MADV_ZEROS true +# elif defined(JEMALLOC_PURGE_MADVISE_FREE) +# define JEMALLOC_MADV_PURGE MADV_FREE +# define JEMALLOC_MADV_ZEROS false +# else +# error "No method defined for purging unused dirty pages." +# endif + int err = madvise(addr, length, JEMALLOC_MADV_PURGE); + unzeroed = (JEMALLOC_MADV_ZEROS == false || err != 0); +# undef JEMALLOC_MADV_PURGE +# undef JEMALLOC_MADV_ZEROS +#endif + return (unzeroed); +} - /* - * If mmap() returned an aligned mapping, reset mmap_unaligned so that - * the next chunk_alloc_mmap() execution tries the fast allocation - * method. - */ - if (unaligned == false) - MMAP_UNALIGNED_SET(false); +static void * +chunk_alloc_mmap_slow(size_t size, size_t alignment, bool *zero) +{ + void *ret, *pages; + size_t alloc_size, leadsize; + alloc_size = size + alignment - PAGE; + /* Beware size_t wrap-around. */ + if (alloc_size < size) + return (NULL); + do { + pages = pages_map(NULL, alloc_size); + if (pages == NULL) + return (NULL); + leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) - + (uintptr_t)pages; + ret = pages_trim(pages, alloc_size, leadsize, size); + } while (ret == NULL); + + assert(ret != NULL); + *zero = true; return (ret); } -static void * -chunk_alloc_mmap_internal(size_t size, bool noreserve) +void * +chunk_alloc_mmap(size_t size, size_t alignment, bool *zero) { void *ret; + size_t offset; /* * Ideally, there would be a way to specify alignment to mmap() (like * NetBSD has), but in the absence of such a feature, we have to work * hard to efficiently create aligned mappings. The reliable, but * slow method is to create a mapping that is over-sized, then trim the - * excess. However, that always results in at least one call to + * excess. However, that always results in one or two calls to * pages_unmap(). * - * A more optimistic approach is to try mapping precisely the right - * amount, then try to append another mapping if alignment is off. In - * practice, this works out well as long as the application is not - * interleaving mappings via direct mmap() calls. If we do run into a - * situation where there is an interleaved mapping and we are unable to - * extend an unaligned mapping, our best option is to switch to the - * slow method until mmap() returns another aligned mapping. This will - * tend to leave a gap in the memory map that is too small to cause - * later problems for the optimistic method. - * - * Another possible confounding factor is address space layout - * randomization (ASLR), which causes mmap(2) to disregard the - * requested address. mmap_unaligned tracks whether the previous - * chunk_alloc_mmap() execution received any unaligned or relocated - * mappings, and if so, the current execution will immediately fall - * back to the slow method. However, we keep track of whether the fast - * method would have succeeded, and if so, we make a note to try the - * fast method next time. + * Optimistically try mapping precisely the right amount before falling + * back to the slow method, with the expectation that the optimistic + * approach works most of the time. */ - if (MMAP_UNALIGNED_GET() == false) { - size_t offset; + assert(alignment != 0); + assert((alignment & chunksize_mask) == 0); - ret = pages_map(NULL, size, noreserve); - if (ret == NULL) - return (NULL); - - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - MMAP_UNALIGNED_SET(true); - /* Try to extend chunk boundary. */ - if (pages_map((void *)((uintptr_t)ret + size), - chunksize - offset, noreserve) == NULL) { - /* - * Extension failed. Clean up, then revert to - * the reliable-but-expensive method. - */ - pages_unmap(ret, size); - ret = chunk_alloc_mmap_slow(size, true, - noreserve); - } else { - /* Clean up unneeded leading space. */ - pages_unmap(ret, chunksize - offset); - ret = (void *)((uintptr_t)ret + (chunksize - - offset)); - } - } - } else - ret = chunk_alloc_mmap_slow(size, false, noreserve); + ret = pages_map(NULL, size); + if (ret == NULL) + return (NULL); + offset = ALIGNMENT_ADDR2OFFSET(ret, alignment); + if (offset != 0) { + pages_unmap(ret, size); + return (chunk_alloc_mmap_slow(size, alignment, zero)); + } + assert(ret != NULL); + *zero = true; return (ret); } -void * -chunk_alloc_mmap(size_t size) -{ - return chunk_alloc_mmap_internal(size, false); -} - -void * -chunk_alloc_mmap_noreserve(size_t size) -{ - return chunk_alloc_mmap_internal(size, true); -} - -void -chunk_dealloc_mmap(void *chunk, size_t size) -{ - - pages_unmap(chunk, size); -} - bool -chunk_mmap_boot(void) +chunk_dealloc_mmap(void *chunk, size_t size) { -#ifdef NO_TLS - if (pthread_key_create(&mmap_unaligned_tsd, NULL) != 0) { - malloc_write("<jemalloc>: Error in pthread_key_create()\n"); - return (true); - } -#endif + if (config_munmap) + pages_unmap(chunk, size); - return (false); + return (config_munmap == false); } diff --git a/dep/jemalloc/src/chunk_swap.c b/dep/jemalloc/src/chunk_swap.c deleted file mode 100644 index cb25ae0dde2..00000000000 --- a/dep/jemalloc/src/chunk_swap.c +++ /dev/null @@ -1,402 +0,0 @@ -#define JEMALLOC_CHUNK_SWAP_C_ -#include "jemalloc/internal/jemalloc_internal.h" -#ifdef JEMALLOC_SWAP -/******************************************************************************/ -/* Data. */ - -malloc_mutex_t swap_mtx; -bool swap_enabled; -bool swap_prezeroed; -size_t swap_nfds; -int *swap_fds; -#ifdef JEMALLOC_STATS -size_t swap_avail; -#endif - -/* Base address of the mmap()ed file(s). */ -static void *swap_base; -/* Current end of the space in use (<= swap_max). */ -static void *swap_end; -/* Absolute upper limit on file-backed addresses. */ -static void *swap_max; - -/* - * Trees of chunks that were previously allocated (trees differ only in node - * ordering). These are used when allocating chunks, in an attempt to re-use - * address space. Depending on function, different tree orderings are needed, - * which is why there are two trees with the same contents. - */ -static extent_tree_t swap_chunks_szad; -static extent_tree_t swap_chunks_ad; - -/******************************************************************************/ -/* Function prototypes for non-inline static functions. */ - -static void *chunk_recycle_swap(size_t size, bool *zero); -static extent_node_t *chunk_dealloc_swap_record(void *chunk, size_t size); - -/******************************************************************************/ - -static void * -chunk_recycle_swap(size_t size, bool *zero) -{ - extent_node_t *node, key; - - key.addr = NULL; - key.size = size; - malloc_mutex_lock(&swap_mtx); - node = extent_tree_szad_nsearch(&swap_chunks_szad, &key); - if (node != NULL) { - void *ret = node->addr; - - /* Remove node from the tree. */ - extent_tree_szad_remove(&swap_chunks_szad, node); - if (node->size == size) { - extent_tree_ad_remove(&swap_chunks_ad, node); - base_node_dealloc(node); - } else { - /* - * Insert the remainder of node's address range as a - * smaller chunk. Its position within swap_chunks_ad - * does not change. - */ - assert(node->size > size); - node->addr = (void *)((uintptr_t)node->addr + size); - node->size -= size; - extent_tree_szad_insert(&swap_chunks_szad, node); - } -#ifdef JEMALLOC_STATS - swap_avail -= size; -#endif - malloc_mutex_unlock(&swap_mtx); - - if (*zero) - memset(ret, 0, size); - return (ret); - } - malloc_mutex_unlock(&swap_mtx); - - return (NULL); -} - -void * -chunk_alloc_swap(size_t size, bool *zero) -{ - void *ret; - - assert(swap_enabled); - - ret = chunk_recycle_swap(size, zero); - if (ret != NULL) - return (ret); - - malloc_mutex_lock(&swap_mtx); - if ((uintptr_t)swap_end + size <= (uintptr_t)swap_max) { - ret = swap_end; - swap_end = (void *)((uintptr_t)swap_end + size); -#ifdef JEMALLOC_STATS - swap_avail -= size; -#endif - malloc_mutex_unlock(&swap_mtx); - - if (swap_prezeroed) - *zero = true; - else if (*zero) - memset(ret, 0, size); - } else { - malloc_mutex_unlock(&swap_mtx); - return (NULL); - } - - return (ret); -} - -static extent_node_t * -chunk_dealloc_swap_record(void *chunk, size_t size) -{ - extent_node_t *xnode, *node, *prev, key; - - xnode = NULL; - while (true) { - key.addr = (void *)((uintptr_t)chunk + size); - node = extent_tree_ad_nsearch(&swap_chunks_ad, &key); - /* Try to coalesce forward. */ - if (node != NULL && node->addr == key.addr) { - /* - * Coalesce chunk with the following address range. - * This does not change the position within - * swap_chunks_ad, so only remove/insert from/into - * swap_chunks_szad. - */ - extent_tree_szad_remove(&swap_chunks_szad, node); - node->addr = chunk; - node->size += size; - extent_tree_szad_insert(&swap_chunks_szad, node); - break; - } else if (xnode == NULL) { - /* - * It is possible that base_node_alloc() will cause a - * new base chunk to be allocated, so take care not to - * deadlock on swap_mtx, and recover if another thread - * deallocates an adjacent chunk while this one is busy - * allocating xnode. - */ - malloc_mutex_unlock(&swap_mtx); - xnode = base_node_alloc(); - malloc_mutex_lock(&swap_mtx); - if (xnode == NULL) - return (NULL); - } else { - /* Coalescing forward failed, so insert a new node. */ - node = xnode; - xnode = NULL; - node->addr = chunk; - node->size = size; - extent_tree_ad_insert(&swap_chunks_ad, node); - extent_tree_szad_insert(&swap_chunks_szad, node); - break; - } - } - /* Discard xnode if it ended up unused do to a race. */ - if (xnode != NULL) - base_node_dealloc(xnode); - - /* Try to coalesce backward. */ - prev = extent_tree_ad_prev(&swap_chunks_ad, node); - if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == - chunk) { - /* - * Coalesce chunk with the previous address range. This does - * not change the position within swap_chunks_ad, so only - * remove/insert node from/into swap_chunks_szad. - */ - extent_tree_szad_remove(&swap_chunks_szad, prev); - extent_tree_ad_remove(&swap_chunks_ad, prev); - - extent_tree_szad_remove(&swap_chunks_szad, node); - node->addr = prev->addr; - node->size += prev->size; - extent_tree_szad_insert(&swap_chunks_szad, node); - - base_node_dealloc(prev); - } - - return (node); -} - -bool -chunk_in_swap(void *chunk) -{ - bool ret; - - assert(swap_enabled); - - malloc_mutex_lock(&swap_mtx); - if ((uintptr_t)chunk >= (uintptr_t)swap_base - && (uintptr_t)chunk < (uintptr_t)swap_max) - ret = true; - else - ret = false; - malloc_mutex_unlock(&swap_mtx); - - return (ret); -} - -bool -chunk_dealloc_swap(void *chunk, size_t size) -{ - bool ret; - - assert(swap_enabled); - - malloc_mutex_lock(&swap_mtx); - if ((uintptr_t)chunk >= (uintptr_t)swap_base - && (uintptr_t)chunk < (uintptr_t)swap_max) { - extent_node_t *node; - - /* Try to coalesce with other unused chunks. */ - node = chunk_dealloc_swap_record(chunk, size); - if (node != NULL) { - chunk = node->addr; - size = node->size; - } - - /* - * Try to shrink the in-use memory if this chunk is at the end - * of the in-use memory. - */ - if ((void *)((uintptr_t)chunk + size) == swap_end) { - swap_end = (void *)((uintptr_t)swap_end - size); - - if (node != NULL) { - extent_tree_szad_remove(&swap_chunks_szad, - node); - extent_tree_ad_remove(&swap_chunks_ad, node); - base_node_dealloc(node); - } - } else - madvise(chunk, size, MADV_DONTNEED); - -#ifdef JEMALLOC_STATS - swap_avail += size; -#endif - ret = false; - goto RETURN; - } - - ret = true; -RETURN: - malloc_mutex_unlock(&swap_mtx); - return (ret); -} - -bool -chunk_swap_enable(const int *fds, unsigned nfds, bool prezeroed) -{ - bool ret; - unsigned i; - off_t off; - void *vaddr; - size_t cumsize, voff; - size_t sizes[nfds]; - - malloc_mutex_lock(&swap_mtx); - - /* Get file sizes. */ - for (i = 0, cumsize = 0; i < nfds; i++) { - off = lseek(fds[i], 0, SEEK_END); - if (off == ((off_t)-1)) { - ret = true; - goto RETURN; - } - if (PAGE_CEILING(off) != off) { - /* Truncate to a multiple of the page size. */ - off &= ~PAGE_MASK; - if (ftruncate(fds[i], off) != 0) { - ret = true; - goto RETURN; - } - } - sizes[i] = off; - if (cumsize + off < cumsize) { - /* - * Cumulative file size is greater than the total - * address space. Bail out while it's still obvious - * what the problem is. - */ - ret = true; - goto RETURN; - } - cumsize += off; - } - - /* Round down to a multiple of the chunk size. */ - cumsize &= ~chunksize_mask; - if (cumsize == 0) { - ret = true; - goto RETURN; - } - - /* - * Allocate a chunk-aligned region of anonymous memory, which will - * be the final location for the memory-mapped files. - */ - vaddr = chunk_alloc_mmap_noreserve(cumsize); - if (vaddr == NULL) { - ret = true; - goto RETURN; - } - - /* Overlay the files onto the anonymous mapping. */ - for (i = 0, voff = 0; i < nfds; i++) { - void *addr = mmap((void *)((uintptr_t)vaddr + voff), sizes[i], - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fds[i], 0); - if (addr == MAP_FAILED) { - char buf[BUFERROR_BUF]; - - - buferror(errno, buf, sizeof(buf)); - malloc_write( - "<jemalloc>: Error in mmap(..., MAP_FIXED, ...): "); - malloc_write(buf); - malloc_write("\n"); - if (opt_abort) - abort(); - if (munmap(vaddr, voff) == -1) { - buferror(errno, buf, sizeof(buf)); - malloc_write("<jemalloc>: Error in munmap(): "); - malloc_write(buf); - malloc_write("\n"); - } - ret = true; - goto RETURN; - } - assert(addr == (void *)((uintptr_t)vaddr + voff)); - - /* - * Tell the kernel that the mapping will be accessed randomly, - * and that it should not gratuitously sync pages to the - * filesystem. - */ -#ifdef MADV_RANDOM - madvise(addr, sizes[i], MADV_RANDOM); -#endif -#ifdef MADV_NOSYNC - madvise(addr, sizes[i], MADV_NOSYNC); -#endif - - voff += sizes[i]; - } - - swap_prezeroed = prezeroed; - swap_base = vaddr; - swap_end = swap_base; - swap_max = (void *)((uintptr_t)vaddr + cumsize); - - /* Copy the fds array for mallctl purposes. */ - swap_fds = (int *)base_alloc(nfds * sizeof(int)); - if (swap_fds == NULL) { - ret = true; - goto RETURN; - } - memcpy(swap_fds, fds, nfds * sizeof(int)); - swap_nfds = nfds; - -#ifdef JEMALLOC_STATS - swap_avail = cumsize; -#endif - - swap_enabled = true; - - ret = false; -RETURN: - malloc_mutex_unlock(&swap_mtx); - return (ret); -} - -bool -chunk_swap_boot(void) -{ - - if (malloc_mutex_init(&swap_mtx)) - return (true); - - swap_enabled = false; - swap_prezeroed = false; /* swap.* mallctl's depend on this. */ - swap_nfds = 0; - swap_fds = NULL; -#ifdef JEMALLOC_STATS - swap_avail = 0; -#endif - swap_base = NULL; - swap_end = NULL; - swap_max = NULL; - - extent_tree_szad_new(&swap_chunks_szad); - extent_tree_ad_new(&swap_chunks_ad); - - return (false); -} - -/******************************************************************************/ -#endif /* JEMALLOC_SWAP */ diff --git a/dep/jemalloc/src/ckh.c b/dep/jemalloc/src/ckh.c index 682a8db65bf..2f38348bb85 100644 --- a/dep/jemalloc/src/ckh.c +++ b/dep/jemalloc/src/ckh.c @@ -34,7 +34,7 @@ * respectively. * ******************************************************************************/ -#define CKH_C_ +#define JEMALLOC_CKH_C_ #include "jemalloc/internal/jemalloc_internal.h" /******************************************************************************/ @@ -70,21 +70,20 @@ ckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key) JEMALLOC_INLINE size_t ckh_isearch(ckh_t *ckh, const void *key) { - size_t hash1, hash2, bucket, cell; + size_t hashes[2], bucket, cell; assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); - ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2); + ckh->hash(key, hashes); /* Search primary bucket. */ - bucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1); + bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1); cell = ckh_bucket_search(ckh, bucket, key); if (cell != SIZE_T_MAX) return (cell); /* Search secondary bucket. */ - bucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1); + bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1); cell = ckh_bucket_search(ckh, bucket, key); return (cell); } @@ -100,7 +99,7 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key, * Cycle through the cells in the bucket, starting at a random position. * The randomness avoids worst-case search overhead as buckets fill up. */ - prn32(offset, LG_CKH_BUCKET_CELLS, ckh->prn_state, CKH_A, CKH_C); + prng32(offset, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C); for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) { cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))]; @@ -127,7 +126,7 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, { const void *key, *data, *tkey, *tdata; ckhc_t *cell; - size_t hash1, hash2, bucket, tbucket; + size_t hashes[2], bucket, tbucket; unsigned i; bucket = argbucket; @@ -142,7 +141,7 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, * were an item for which both hashes indicated the same * bucket. */ - prn32(i, LG_CKH_BUCKET_CELLS, ckh->prn_state, CKH_A, CKH_C); + prng32(i, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C); cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i]; assert(cell->key != NULL); @@ -156,10 +155,11 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, #endif /* Find the alternate bucket for the evicted item. */ - ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2); - tbucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1); + ckh->hash(key, hashes); + tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1); if (tbucket == bucket) { - tbucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1); + tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) + - 1); /* * It may be that (tbucket == bucket) still, if the * item's hashes both indicate this bucket. However, @@ -193,19 +193,19 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, JEMALLOC_INLINE bool ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata) { - size_t hash1, hash2, bucket; + size_t hashes[2], bucket; const void *key = *argkey; const void *data = *argdata; - ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2); + ckh->hash(key, hashes); /* Try to insert in primary bucket. */ - bucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1); + bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1); if (ckh_try_bucket_insert(ckh, bucket, key, data) == false) return (false); /* Try to insert in secondary bucket. */ - bucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1); + bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1); if (ckh_try_bucket_insert(ckh, bucket, key, data) == false) return (false); @@ -262,12 +262,18 @@ ckh_grow(ckh_t *ckh) lg_prevbuckets = ckh->lg_curbuckets; lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS; while (true) { + size_t usize; + lg_curcells++; - tab = (ckhc_t *)ipalloc(sizeof(ckhc_t) << lg_curcells, - ZU(1) << LG_CACHELINE, true); + usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); + if (usize == 0) { + ret = true; + goto label_return; + } + tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); if (tab == NULL) { ret = true; - goto RETURN; + goto label_return; } /* Swap in new table. */ ttab = ckh->tab; @@ -287,7 +293,7 @@ ckh_grow(ckh_t *ckh) } ret = false; -RETURN: +label_return: return (ret); } @@ -295,7 +301,7 @@ static void ckh_shrink(ckh_t *ckh) { ckhc_t *tab, *ttab; - size_t lg_curcells; + size_t lg_curcells, usize; unsigned lg_prevbuckets; /* @@ -304,8 +310,10 @@ ckh_shrink(ckh_t *ckh) */ lg_prevbuckets = ckh->lg_curbuckets; lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1; - tab = (ckhc_t *)ipalloc(sizeof(ckhc_t) << lg_curcells, - ZU(1) << LG_CACHELINE, true); + usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); + if (usize == 0) + return; + tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); if (tab == NULL) { /* * An OOM error isn't worth propagating, since it doesn't @@ -340,7 +348,7 @@ bool ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) { bool ret; - size_t mincells; + size_t mincells, usize; unsigned lg_mincells; assert(minitems > 0); @@ -354,7 +362,7 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) ckh->ninserts = 0; ckh->nrelocs = 0; #endif - ckh->prn_state = 42; /* Value doesn't really matter. */ + ckh->prng_state = 42; /* Value doesn't really matter. */ ckh->count = 0; /* @@ -375,19 +383,19 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) ckh->hash = hash; ckh->keycomp = keycomp; - ckh->tab = (ckhc_t *)ipalloc(sizeof(ckhc_t) << lg_mincells, - (ZU(1) << LG_CACHELINE), true); + usize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE); + if (usize == 0) { + ret = true; + goto label_return; + } + ckh->tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); if (ckh->tab == NULL) { ret = true; - goto RETURN; + goto label_return; } -#ifdef JEMALLOC_DEBUG - ckh->magic = CKH_MAGIG; -#endif - ret = false; -RETURN: +label_return: return (ret); } @@ -396,7 +404,6 @@ ckh_delete(ckh_t *ckh) { assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); #ifdef CKH_VERBOSE malloc_printf( @@ -411,9 +418,8 @@ ckh_delete(ckh_t *ckh) #endif idalloc(ckh->tab); -#ifdef JEMALLOC_DEBUG - memset(ckh, 0x5a, sizeof(ckh_t)); -#endif + if (config_debug) + memset(ckh, 0x5a, sizeof(ckh_t)); } size_t @@ -421,7 +427,6 @@ ckh_count(ckh_t *ckh) { assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); return (ckh->count); } @@ -452,7 +457,6 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data) bool ret; assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); assert(ckh_search(ckh, key, NULL, NULL)); #ifdef CKH_COUNT @@ -462,12 +466,12 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data) while (ckh_try_insert(ckh, &key, &data)) { if (ckh_grow(ckh)) { ret = true; - goto RETURN; + goto label_return; } } ret = false; -RETURN: +label_return: return (ret); } @@ -477,7 +481,6 @@ ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data) size_t cell; assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); cell = ckh_isearch(ckh, searchkey); if (cell != SIZE_T_MAX) { @@ -509,7 +512,6 @@ ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data) size_t cell; assert(ckh != NULL); - assert(ckh->magic = CKH_MAGIG); cell = ckh_isearch(ckh, searchkey); if (cell != SIZE_T_MAX) { @@ -524,31 +526,10 @@ ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data) } void -ckh_string_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2) +ckh_string_hash(const void *key, size_t r_hash[2]) { - size_t ret1, ret2; - uint64_t h; - - assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64)); - assert(hash1 != NULL); - assert(hash2 != NULL); - h = hash(key, strlen((const char *)key), 0x94122f335b332aeaLLU); - if (minbits <= 32) { - /* - * Avoid doing multiple hashes, since a single hash provides - * enough bits. - */ - ret1 = h & ZU(0xffffffffU); - ret2 = h >> 32; - } else { - ret1 = h; - ret2 = hash(key, strlen((const char *)key), - 0x8432a476666bbc13U); - } - - *hash1 = ret1; - *hash2 = ret2; + hash(key, strlen((const char *)key), 0x94122f33U, r_hash); } bool @@ -562,41 +543,16 @@ ckh_string_keycomp(const void *k1, const void *k2) } void -ckh_pointer_hash(const void *key, unsigned minbits, size_t *hash1, - size_t *hash2) +ckh_pointer_hash(const void *key, size_t r_hash[2]) { - size_t ret1, ret2; - uint64_t h; union { const void *v; - uint64_t i; + size_t i; } u; - assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64)); - assert(hash1 != NULL); - assert(hash2 != NULL); - assert(sizeof(u.v) == sizeof(u.i)); -#if (LG_SIZEOF_PTR != LG_SIZEOF_INT) - u.i = 0; -#endif u.v = key; - h = hash(&u.i, sizeof(u.i), 0xd983396e68886082LLU); - if (minbits <= 32) { - /* - * Avoid doing multiple hashes, since a single hash provides - * enough bits. - */ - ret1 = h & ZU(0xffffffffU); - ret2 = h >> 32; - } else { - assert(SIZEOF_PTR == 8); - ret1 = h; - ret2 = hash(&u.i, sizeof(u.i), 0x5e2be9aff8709a5dLLU); - } - - *hash1 = ret1; - *hash2 = ret2; + hash(&u.i, sizeof(u.i), 0xd983396eU, r_hash); } bool diff --git a/dep/jemalloc/src/ctl.c b/dep/jemalloc/src/ctl.c index 3c8adab90a3..f2ef4e60611 100644 --- a/dep/jemalloc/src/ctl.c +++ b/dep/jemalloc/src/ctl.c @@ -8,8 +8,6 @@ * ctl_mtx protects the following: * - ctl_stats.* * - opt_prof_active - * - swap_enabled - * - swap_prezeroed */ static malloc_mutex_t ctl_mtx; static bool ctl_initialized; @@ -17,6 +15,32 @@ static uint64_t ctl_epoch; static ctl_stats_t ctl_stats; /******************************************************************************/ +/* Helpers for named and indexed nodes. */ + +static inline const ctl_named_node_t * +ctl_named_node(const ctl_node_t *node) +{ + + return ((node->named) ? (const ctl_named_node_t *)node : NULL); +} + +static inline const ctl_named_node_t * +ctl_named_children(const ctl_named_node_t *node, int index) +{ + const ctl_named_node_t *children = ctl_named_node(node->children); + + return (children ? &children[index] : NULL); +} + +static inline const ctl_indexed_node_t * +ctl_indexed_node(const ctl_node_t *node) +{ + + return ((node->named == false) ? (const ctl_indexed_node_t *)node : + NULL); +} + +/******************************************************************************/ /* Function prototypes for non-inline static functions. */ #define CTL_PROTO(n) \ @@ -24,20 +48,17 @@ static int n##_ctl(const size_t *mib, size_t miblen, void *oldp, \ size_t *oldlenp, void *newp, size_t newlen); #define INDEX_PROTO(n) \ -const ctl_node_t *n##_index(const size_t *mib, size_t miblen, \ - size_t i); +static const ctl_named_node_t *n##_index(const size_t *mib, \ + size_t miblen, size_t i); -#ifdef JEMALLOC_STATS static bool ctl_arena_init(ctl_arena_stats_t *astats); -#endif static void ctl_arena_clear(ctl_arena_stats_t *astats); -#ifdef JEMALLOC_STATS static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena); static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats); -#endif static void ctl_arena_refresh(arena_t *arena, unsigned i); +static bool ctl_grow(void); static void ctl_refresh(void); static bool ctl_init(void); static int ctl_lookup(const char *name, ctl_node_t const **nodesp, @@ -45,67 +66,56 @@ static int ctl_lookup(const char *name, ctl_node_t const **nodesp, CTL_PROTO(version) CTL_PROTO(epoch) -#ifdef JEMALLOC_TCACHE -CTL_PROTO(tcache_flush) -#endif +CTL_PROTO(thread_tcache_enabled) +CTL_PROTO(thread_tcache_flush) CTL_PROTO(thread_arena) -#ifdef JEMALLOC_STATS CTL_PROTO(thread_allocated) CTL_PROTO(thread_allocatedp) CTL_PROTO(thread_deallocated) CTL_PROTO(thread_deallocatedp) -#endif CTL_PROTO(config_debug) CTL_PROTO(config_dss) -CTL_PROTO(config_dynamic_page_shift) CTL_PROTO(config_fill) CTL_PROTO(config_lazy_lock) +CTL_PROTO(config_mremap) +CTL_PROTO(config_munmap) CTL_PROTO(config_prof) CTL_PROTO(config_prof_libgcc) CTL_PROTO(config_prof_libunwind) CTL_PROTO(config_stats) -CTL_PROTO(config_swap) -CTL_PROTO(config_sysv) CTL_PROTO(config_tcache) -CTL_PROTO(config_tiny) CTL_PROTO(config_tls) +CTL_PROTO(config_utrace) +CTL_PROTO(config_valgrind) CTL_PROTO(config_xmalloc) CTL_PROTO(opt_abort) -CTL_PROTO(opt_lg_qspace_max) -CTL_PROTO(opt_lg_cspace_max) +CTL_PROTO(opt_dss) CTL_PROTO(opt_lg_chunk) CTL_PROTO(opt_narenas) CTL_PROTO(opt_lg_dirty_mult) CTL_PROTO(opt_stats_print) -#ifdef JEMALLOC_FILL CTL_PROTO(opt_junk) CTL_PROTO(opt_zero) -#endif -#ifdef JEMALLOC_SYSV -CTL_PROTO(opt_sysv) -#endif -#ifdef JEMALLOC_XMALLOC +CTL_PROTO(opt_quarantine) +CTL_PROTO(opt_redzone) +CTL_PROTO(opt_utrace) +CTL_PROTO(opt_valgrind) CTL_PROTO(opt_xmalloc) -#endif -#ifdef JEMALLOC_TCACHE CTL_PROTO(opt_tcache) -CTL_PROTO(opt_lg_tcache_gc_sweep) -#endif -#ifdef JEMALLOC_PROF +CTL_PROTO(opt_lg_tcache_max) CTL_PROTO(opt_prof) CTL_PROTO(opt_prof_prefix) CTL_PROTO(opt_prof_active) -CTL_PROTO(opt_lg_prof_bt_max) CTL_PROTO(opt_lg_prof_sample) CTL_PROTO(opt_lg_prof_interval) CTL_PROTO(opt_prof_gdump) +CTL_PROTO(opt_prof_final) CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_accum) -CTL_PROTO(opt_lg_prof_tcmax) -#endif -#ifdef JEMALLOC_SWAP -CTL_PROTO(opt_overcommit) -#endif +CTL_PROTO(arena_i_purge) +static void arena_purge(unsigned arena_ind); +CTL_PROTO(arena_i_dss) +INDEX_PROTO(arena_i) CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_nregs) CTL_PROTO(arenas_bin_i_run_size) @@ -115,39 +125,16 @@ INDEX_PROTO(arenas_lrun_i) CTL_PROTO(arenas_narenas) CTL_PROTO(arenas_initialized) CTL_PROTO(arenas_quantum) -CTL_PROTO(arenas_cacheline) -CTL_PROTO(arenas_subpage) -CTL_PROTO(arenas_pagesize) -CTL_PROTO(arenas_chunksize) -#ifdef JEMALLOC_TINY -CTL_PROTO(arenas_tspace_min) -CTL_PROTO(arenas_tspace_max) -#endif -CTL_PROTO(arenas_qspace_min) -CTL_PROTO(arenas_qspace_max) -CTL_PROTO(arenas_cspace_min) -CTL_PROTO(arenas_cspace_max) -CTL_PROTO(arenas_sspace_min) -CTL_PROTO(arenas_sspace_max) -#ifdef JEMALLOC_TCACHE +CTL_PROTO(arenas_page) CTL_PROTO(arenas_tcache_max) -#endif -CTL_PROTO(arenas_ntbins) -CTL_PROTO(arenas_nqbins) -CTL_PROTO(arenas_ncbins) -CTL_PROTO(arenas_nsbins) CTL_PROTO(arenas_nbins) -#ifdef JEMALLOC_TCACHE CTL_PROTO(arenas_nhbins) -#endif CTL_PROTO(arenas_nlruns) CTL_PROTO(arenas_purge) -#ifdef JEMALLOC_PROF +CTL_PROTO(arenas_extend) CTL_PROTO(prof_active) CTL_PROTO(prof_dump) CTL_PROTO(prof_interval) -#endif -#ifdef JEMALLOC_STATS CTL_PROTO(stats_chunks_current) CTL_PROTO(stats_chunks_total) CTL_PROTO(stats_chunks_high) @@ -166,44 +153,30 @@ CTL_PROTO(stats_arenas_i_bins_j_allocated) CTL_PROTO(stats_arenas_i_bins_j_nmalloc) CTL_PROTO(stats_arenas_i_bins_j_ndalloc) CTL_PROTO(stats_arenas_i_bins_j_nrequests) -#ifdef JEMALLOC_TCACHE CTL_PROTO(stats_arenas_i_bins_j_nfills) CTL_PROTO(stats_arenas_i_bins_j_nflushes) -#endif CTL_PROTO(stats_arenas_i_bins_j_nruns) CTL_PROTO(stats_arenas_i_bins_j_nreruns) -CTL_PROTO(stats_arenas_i_bins_j_highruns) CTL_PROTO(stats_arenas_i_bins_j_curruns) INDEX_PROTO(stats_arenas_i_bins_j) CTL_PROTO(stats_arenas_i_lruns_j_nmalloc) CTL_PROTO(stats_arenas_i_lruns_j_ndalloc) CTL_PROTO(stats_arenas_i_lruns_j_nrequests) -CTL_PROTO(stats_arenas_i_lruns_j_highruns) CTL_PROTO(stats_arenas_i_lruns_j_curruns) INDEX_PROTO(stats_arenas_i_lruns_j) -#endif +CTL_PROTO(stats_arenas_i_nthreads) +CTL_PROTO(stats_arenas_i_dss) CTL_PROTO(stats_arenas_i_pactive) CTL_PROTO(stats_arenas_i_pdirty) -#ifdef JEMALLOC_STATS CTL_PROTO(stats_arenas_i_mapped) CTL_PROTO(stats_arenas_i_npurge) CTL_PROTO(stats_arenas_i_nmadvise) CTL_PROTO(stats_arenas_i_purged) -#endif INDEX_PROTO(stats_arenas_i) -#ifdef JEMALLOC_STATS +CTL_PROTO(stats_cactive) CTL_PROTO(stats_allocated) CTL_PROTO(stats_active) CTL_PROTO(stats_mapped) -#endif -#ifdef JEMALLOC_SWAP -# ifdef JEMALLOC_STATS -CTL_PROTO(swap_avail) -# endif -CTL_PROTO(swap_prezeroed) -CTL_PROTO(swap_nfds) -CTL_PROTO(swap_fds) -#endif /******************************************************************************/ /* mallctl tree. */ @@ -211,294 +184,239 @@ CTL_PROTO(swap_fds) /* Maximum tree depth. */ #define CTL_MAX_DEPTH 6 -#define NAME(n) true, {.named = {n -#define CHILD(c) sizeof(c##_node) / sizeof(ctl_node_t), c##_node}}, NULL -#define CTL(c) 0, NULL}}, c##_ctl +#define NAME(n) {true}, n +#define CHILD(t, c) \ + sizeof(c##_node) / sizeof(ctl_##t##_node_t), \ + (ctl_node_t *)c##_node, \ + NULL +#define CTL(c) 0, NULL, c##_ctl /* * Only handles internal indexed nodes, since there are currently no external * ones. */ -#define INDEX(i) false, {.indexed = {i##_index}}, NULL +#define INDEX(i) {false}, i##_index -#ifdef JEMALLOC_TCACHE -static const ctl_node_t tcache_node[] = { - {NAME("flush"), CTL(tcache_flush)} +static const ctl_named_node_t tcache_node[] = { + {NAME("enabled"), CTL(thread_tcache_enabled)}, + {NAME("flush"), CTL(thread_tcache_flush)} }; -#endif -static const ctl_node_t thread_node[] = { - {NAME("arena"), CTL(thread_arena)} -#ifdef JEMALLOC_STATS - , +static const ctl_named_node_t thread_node[] = { + {NAME("arena"), CTL(thread_arena)}, {NAME("allocated"), CTL(thread_allocated)}, {NAME("allocatedp"), CTL(thread_allocatedp)}, {NAME("deallocated"), CTL(thread_deallocated)}, - {NAME("deallocatedp"), CTL(thread_deallocatedp)} -#endif + {NAME("deallocatedp"), CTL(thread_deallocatedp)}, + {NAME("tcache"), CHILD(named, tcache)} }; -static const ctl_node_t config_node[] = { +static const ctl_named_node_t config_node[] = { {NAME("debug"), CTL(config_debug)}, {NAME("dss"), CTL(config_dss)}, - {NAME("dynamic_page_shift"), CTL(config_dynamic_page_shift)}, {NAME("fill"), CTL(config_fill)}, {NAME("lazy_lock"), CTL(config_lazy_lock)}, + {NAME("mremap"), CTL(config_mremap)}, + {NAME("munmap"), CTL(config_munmap)}, {NAME("prof"), CTL(config_prof)}, {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, {NAME("stats"), CTL(config_stats)}, - {NAME("swap"), CTL(config_swap)}, - {NAME("sysv"), CTL(config_sysv)}, {NAME("tcache"), CTL(config_tcache)}, - {NAME("tiny"), CTL(config_tiny)}, {NAME("tls"), CTL(config_tls)}, + {NAME("utrace"), CTL(config_utrace)}, + {NAME("valgrind"), CTL(config_valgrind)}, {NAME("xmalloc"), CTL(config_xmalloc)} }; -static const ctl_node_t opt_node[] = { +static const ctl_named_node_t opt_node[] = { {NAME("abort"), CTL(opt_abort)}, - {NAME("lg_qspace_max"), CTL(opt_lg_qspace_max)}, - {NAME("lg_cspace_max"), CTL(opt_lg_cspace_max)}, + {NAME("dss"), CTL(opt_dss)}, {NAME("lg_chunk"), CTL(opt_lg_chunk)}, {NAME("narenas"), CTL(opt_narenas)}, {NAME("lg_dirty_mult"), CTL(opt_lg_dirty_mult)}, - {NAME("stats_print"), CTL(opt_stats_print)} -#ifdef JEMALLOC_FILL - , + {NAME("stats_print"), CTL(opt_stats_print)}, {NAME("junk"), CTL(opt_junk)}, - {NAME("zero"), CTL(opt_zero)} -#endif -#ifdef JEMALLOC_SYSV - , - {NAME("sysv"), CTL(opt_sysv)} -#endif -#ifdef JEMALLOC_XMALLOC - , - {NAME("xmalloc"), CTL(opt_xmalloc)} -#endif -#ifdef JEMALLOC_TCACHE - , + {NAME("zero"), CTL(opt_zero)}, + {NAME("quarantine"), CTL(opt_quarantine)}, + {NAME("redzone"), CTL(opt_redzone)}, + {NAME("utrace"), CTL(opt_utrace)}, + {NAME("valgrind"), CTL(opt_valgrind)}, + {NAME("xmalloc"), CTL(opt_xmalloc)}, {NAME("tcache"), CTL(opt_tcache)}, - {NAME("lg_tcache_gc_sweep"), CTL(opt_lg_tcache_gc_sweep)} -#endif -#ifdef JEMALLOC_PROF - , + {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, {NAME("prof"), CTL(opt_prof)}, {NAME("prof_prefix"), CTL(opt_prof_prefix)}, {NAME("prof_active"), CTL(opt_prof_active)}, - {NAME("lg_prof_bt_max"), CTL(opt_lg_prof_bt_max)}, {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)}, {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)}, {NAME("prof_gdump"), CTL(opt_prof_gdump)}, + {NAME("prof_final"), CTL(opt_prof_final)}, {NAME("prof_leak"), CTL(opt_prof_leak)}, - {NAME("prof_accum"), CTL(opt_prof_accum)}, - {NAME("lg_prof_tcmax"), CTL(opt_lg_prof_tcmax)} -#endif -#ifdef JEMALLOC_SWAP - , - {NAME("overcommit"), CTL(opt_overcommit)} -#endif + {NAME("prof_accum"), CTL(opt_prof_accum)} }; -static const ctl_node_t arenas_bin_i_node[] = { +static const ctl_named_node_t arena_i_node[] = { + {NAME("purge"), CTL(arena_i_purge)}, + {NAME("dss"), CTL(arena_i_dss)} +}; +static const ctl_named_node_t super_arena_i_node[] = { + {NAME(""), CHILD(named, arena_i)} +}; + +static const ctl_indexed_node_t arena_node[] = { + {INDEX(arena_i)} +}; + +static const ctl_named_node_t arenas_bin_i_node[] = { {NAME("size"), CTL(arenas_bin_i_size)}, {NAME("nregs"), CTL(arenas_bin_i_nregs)}, {NAME("run_size"), CTL(arenas_bin_i_run_size)} }; -static const ctl_node_t super_arenas_bin_i_node[] = { - {NAME(""), CHILD(arenas_bin_i)} +static const ctl_named_node_t super_arenas_bin_i_node[] = { + {NAME(""), CHILD(named, arenas_bin_i)} }; -static const ctl_node_t arenas_bin_node[] = { +static const ctl_indexed_node_t arenas_bin_node[] = { {INDEX(arenas_bin_i)} }; -static const ctl_node_t arenas_lrun_i_node[] = { +static const ctl_named_node_t arenas_lrun_i_node[] = { {NAME("size"), CTL(arenas_lrun_i_size)} }; -static const ctl_node_t super_arenas_lrun_i_node[] = { - {NAME(""), CHILD(arenas_lrun_i)} +static const ctl_named_node_t super_arenas_lrun_i_node[] = { + {NAME(""), CHILD(named, arenas_lrun_i)} }; -static const ctl_node_t arenas_lrun_node[] = { +static const ctl_indexed_node_t arenas_lrun_node[] = { {INDEX(arenas_lrun_i)} }; -static const ctl_node_t arenas_node[] = { +static const ctl_named_node_t arenas_node[] = { {NAME("narenas"), CTL(arenas_narenas)}, {NAME("initialized"), CTL(arenas_initialized)}, {NAME("quantum"), CTL(arenas_quantum)}, - {NAME("cacheline"), CTL(arenas_cacheline)}, - {NAME("subpage"), CTL(arenas_subpage)}, - {NAME("pagesize"), CTL(arenas_pagesize)}, - {NAME("chunksize"), CTL(arenas_chunksize)}, -#ifdef JEMALLOC_TINY - {NAME("tspace_min"), CTL(arenas_tspace_min)}, - {NAME("tspace_max"), CTL(arenas_tspace_max)}, -#endif - {NAME("qspace_min"), CTL(arenas_qspace_min)}, - {NAME("qspace_max"), CTL(arenas_qspace_max)}, - {NAME("cspace_min"), CTL(arenas_cspace_min)}, - {NAME("cspace_max"), CTL(arenas_cspace_max)}, - {NAME("sspace_min"), CTL(arenas_sspace_min)}, - {NAME("sspace_max"), CTL(arenas_sspace_max)}, -#ifdef JEMALLOC_TCACHE + {NAME("page"), CTL(arenas_page)}, {NAME("tcache_max"), CTL(arenas_tcache_max)}, -#endif - {NAME("ntbins"), CTL(arenas_ntbins)}, - {NAME("nqbins"), CTL(arenas_nqbins)}, - {NAME("ncbins"), CTL(arenas_ncbins)}, - {NAME("nsbins"), CTL(arenas_nsbins)}, {NAME("nbins"), CTL(arenas_nbins)}, -#ifdef JEMALLOC_TCACHE {NAME("nhbins"), CTL(arenas_nhbins)}, -#endif - {NAME("bin"), CHILD(arenas_bin)}, + {NAME("bin"), CHILD(indexed, arenas_bin)}, {NAME("nlruns"), CTL(arenas_nlruns)}, - {NAME("lrun"), CHILD(arenas_lrun)}, - {NAME("purge"), CTL(arenas_purge)} + {NAME("lrun"), CHILD(indexed, arenas_lrun)}, + {NAME("purge"), CTL(arenas_purge)}, + {NAME("extend"), CTL(arenas_extend)} }; -#ifdef JEMALLOC_PROF -static const ctl_node_t prof_node[] = { +static const ctl_named_node_t prof_node[] = { {NAME("active"), CTL(prof_active)}, {NAME("dump"), CTL(prof_dump)}, {NAME("interval"), CTL(prof_interval)} }; -#endif -#ifdef JEMALLOC_STATS -static const ctl_node_t stats_chunks_node[] = { +static const ctl_named_node_t stats_chunks_node[] = { {NAME("current"), CTL(stats_chunks_current)}, {NAME("total"), CTL(stats_chunks_total)}, {NAME("high"), CTL(stats_chunks_high)} }; -static const ctl_node_t stats_huge_node[] = { +static const ctl_named_node_t stats_huge_node[] = { {NAME("allocated"), CTL(stats_huge_allocated)}, {NAME("nmalloc"), CTL(stats_huge_nmalloc)}, {NAME("ndalloc"), CTL(stats_huge_ndalloc)} }; -static const ctl_node_t stats_arenas_i_small_node[] = { +static const ctl_named_node_t stats_arenas_i_small_node[] = { {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)}, {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)} }; -static const ctl_node_t stats_arenas_i_large_node[] = { +static const ctl_named_node_t stats_arenas_i_large_node[] = { {NAME("allocated"), CTL(stats_arenas_i_large_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)}, {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)}, {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)} }; -static const ctl_node_t stats_arenas_i_bins_j_node[] = { +static const ctl_named_node_t stats_arenas_i_bins_j_node[] = { {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)}, {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)}, {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)}, {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)}, -#ifdef JEMALLOC_TCACHE {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)}, {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)}, -#endif {NAME("nruns"), CTL(stats_arenas_i_bins_j_nruns)}, {NAME("nreruns"), CTL(stats_arenas_i_bins_j_nreruns)}, - {NAME("highruns"), CTL(stats_arenas_i_bins_j_highruns)}, {NAME("curruns"), CTL(stats_arenas_i_bins_j_curruns)} }; -static const ctl_node_t super_stats_arenas_i_bins_j_node[] = { - {NAME(""), CHILD(stats_arenas_i_bins_j)} +static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = { + {NAME(""), CHILD(named, stats_arenas_i_bins_j)} }; -static const ctl_node_t stats_arenas_i_bins_node[] = { +static const ctl_indexed_node_t stats_arenas_i_bins_node[] = { {INDEX(stats_arenas_i_bins_j)} }; -static const ctl_node_t stats_arenas_i_lruns_j_node[] = { +static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = { {NAME("nmalloc"), CTL(stats_arenas_i_lruns_j_nmalloc)}, {NAME("ndalloc"), CTL(stats_arenas_i_lruns_j_ndalloc)}, {NAME("nrequests"), CTL(stats_arenas_i_lruns_j_nrequests)}, - {NAME("highruns"), CTL(stats_arenas_i_lruns_j_highruns)}, {NAME("curruns"), CTL(stats_arenas_i_lruns_j_curruns)} }; -static const ctl_node_t super_stats_arenas_i_lruns_j_node[] = { - {NAME(""), CHILD(stats_arenas_i_lruns_j)} +static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = { + {NAME(""), CHILD(named, stats_arenas_i_lruns_j)} }; -static const ctl_node_t stats_arenas_i_lruns_node[] = { +static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = { {INDEX(stats_arenas_i_lruns_j)} }; -#endif -static const ctl_node_t stats_arenas_i_node[] = { +static const ctl_named_node_t stats_arenas_i_node[] = { + {NAME("nthreads"), CTL(stats_arenas_i_nthreads)}, + {NAME("dss"), CTL(stats_arenas_i_dss)}, {NAME("pactive"), CTL(stats_arenas_i_pactive)}, - {NAME("pdirty"), CTL(stats_arenas_i_pdirty)} -#ifdef JEMALLOC_STATS - , + {NAME("pdirty"), CTL(stats_arenas_i_pdirty)}, {NAME("mapped"), CTL(stats_arenas_i_mapped)}, {NAME("npurge"), CTL(stats_arenas_i_npurge)}, {NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)}, {NAME("purged"), CTL(stats_arenas_i_purged)}, - {NAME("small"), CHILD(stats_arenas_i_small)}, - {NAME("large"), CHILD(stats_arenas_i_large)}, - {NAME("bins"), CHILD(stats_arenas_i_bins)}, - {NAME("lruns"), CHILD(stats_arenas_i_lruns)} -#endif + {NAME("small"), CHILD(named, stats_arenas_i_small)}, + {NAME("large"), CHILD(named, stats_arenas_i_large)}, + {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)}, + {NAME("lruns"), CHILD(indexed, stats_arenas_i_lruns)} }; -static const ctl_node_t super_stats_arenas_i_node[] = { - {NAME(""), CHILD(stats_arenas_i)} +static const ctl_named_node_t super_stats_arenas_i_node[] = { + {NAME(""), CHILD(named, stats_arenas_i)} }; -static const ctl_node_t stats_arenas_node[] = { +static const ctl_indexed_node_t stats_arenas_node[] = { {INDEX(stats_arenas_i)} }; -static const ctl_node_t stats_node[] = { -#ifdef JEMALLOC_STATS +static const ctl_named_node_t stats_node[] = { + {NAME("cactive"), CTL(stats_cactive)}, {NAME("allocated"), CTL(stats_allocated)}, {NAME("active"), CTL(stats_active)}, {NAME("mapped"), CTL(stats_mapped)}, - {NAME("chunks"), CHILD(stats_chunks)}, - {NAME("huge"), CHILD(stats_huge)}, -#endif - {NAME("arenas"), CHILD(stats_arenas)} -}; - -#ifdef JEMALLOC_SWAP -static const ctl_node_t swap_node[] = { -# ifdef JEMALLOC_STATS - {NAME("avail"), CTL(swap_avail)}, -# endif - {NAME("prezeroed"), CTL(swap_prezeroed)}, - {NAME("nfds"), CTL(swap_nfds)}, - {NAME("fds"), CTL(swap_fds)} + {NAME("chunks"), CHILD(named, stats_chunks)}, + {NAME("huge"), CHILD(named, stats_huge)}, + {NAME("arenas"), CHILD(indexed, stats_arenas)} }; -#endif -static const ctl_node_t root_node[] = { +static const ctl_named_node_t root_node[] = { {NAME("version"), CTL(version)}, {NAME("epoch"), CTL(epoch)}, -#ifdef JEMALLOC_TCACHE - {NAME("tcache"), CHILD(tcache)}, -#endif - {NAME("thread"), CHILD(thread)}, - {NAME("config"), CHILD(config)}, - {NAME("opt"), CHILD(opt)}, - {NAME("arenas"), CHILD(arenas)}, -#ifdef JEMALLOC_PROF - {NAME("prof"), CHILD(prof)}, -#endif - {NAME("stats"), CHILD(stats)} -#ifdef JEMALLOC_SWAP - , - {NAME("swap"), CHILD(swap)} -#endif + {NAME("thread"), CHILD(named, thread)}, + {NAME("config"), CHILD(named, config)}, + {NAME("opt"), CHILD(named, opt)}, + {NAME("arena"), CHILD(indexed, arena)}, + {NAME("arenas"), CHILD(named, arenas)}, + {NAME("prof"), CHILD(named, prof)}, + {NAME("stats"), CHILD(named, stats)} }; -static const ctl_node_t super_root_node[] = { - {NAME(""), CHILD(root)} +static const ctl_named_node_t super_root_node[] = { + {NAME(""), CHILD(named, root)} }; #undef NAME @@ -508,17 +426,10 @@ static const ctl_node_t super_root_node[] = { /******************************************************************************/ -#ifdef JEMALLOC_STATS static bool ctl_arena_init(ctl_arena_stats_t *astats) { - if (astats->bstats == NULL) { - astats->bstats = (malloc_bin_stats_t *)base_alloc(nbins * - sizeof(malloc_bin_stats_t)); - if (astats->bstats == NULL) - return (true); - } if (astats->lstats == NULL) { astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses * sizeof(malloc_large_stats_t)); @@ -528,35 +439,35 @@ ctl_arena_init(ctl_arena_stats_t *astats) return (false); } -#endif static void ctl_arena_clear(ctl_arena_stats_t *astats) { + astats->dss = dss_prec_names[dss_prec_limit]; astats->pactive = 0; astats->pdirty = 0; -#ifdef JEMALLOC_STATS - memset(&astats->astats, 0, sizeof(arena_stats_t)); - astats->allocated_small = 0; - astats->nmalloc_small = 0; - astats->ndalloc_small = 0; - astats->nrequests_small = 0; - memset(astats->bstats, 0, nbins * sizeof(malloc_bin_stats_t)); - memset(astats->lstats, 0, nlclasses * sizeof(malloc_large_stats_t)); -#endif + if (config_stats) { + memset(&astats->astats, 0, sizeof(arena_stats_t)); + astats->allocated_small = 0; + astats->nmalloc_small = 0; + astats->ndalloc_small = 0; + astats->nrequests_small = 0; + memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t)); + memset(astats->lstats, 0, nlclasses * + sizeof(malloc_large_stats_t)); + } } -#ifdef JEMALLOC_STATS static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena) { unsigned i; - arena_stats_merge(arena, &cstats->pactive, &cstats->pdirty, - &cstats->astats, cstats->bstats, cstats->lstats); + arena_stats_merge(arena, &cstats->dss, &cstats->pactive, + &cstats->pdirty, &cstats->astats, cstats->bstats, cstats->lstats); - for (i = 0; i < nbins; i++) { + for (i = 0; i < NBINS; i++) { cstats->allocated_small += cstats->bstats[i].allocated; cstats->nmalloc_small += cstats->bstats[i].nmalloc; cstats->ndalloc_small += cstats->bstats[i].ndalloc; @@ -591,78 +502,145 @@ ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats) sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc; sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc; sstats->lstats[i].nrequests += astats->lstats[i].nrequests; - sstats->lstats[i].highruns += astats->lstats[i].highruns; sstats->lstats[i].curruns += astats->lstats[i].curruns; } - for (i = 0; i < nbins; i++) { + for (i = 0; i < NBINS; i++) { sstats->bstats[i].allocated += astats->bstats[i].allocated; sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc; sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc; sstats->bstats[i].nrequests += astats->bstats[i].nrequests; -#ifdef JEMALLOC_TCACHE - sstats->bstats[i].nfills += astats->bstats[i].nfills; - sstats->bstats[i].nflushes += astats->bstats[i].nflushes; -#endif + if (config_tcache) { + sstats->bstats[i].nfills += astats->bstats[i].nfills; + sstats->bstats[i].nflushes += + astats->bstats[i].nflushes; + } sstats->bstats[i].nruns += astats->bstats[i].nruns; sstats->bstats[i].reruns += astats->bstats[i].reruns; - sstats->bstats[i].highruns += astats->bstats[i].highruns; sstats->bstats[i].curruns += astats->bstats[i].curruns; } } -#endif static void ctl_arena_refresh(arena_t *arena, unsigned i) { ctl_arena_stats_t *astats = &ctl_stats.arenas[i]; - ctl_arena_stats_t *sstats = &ctl_stats.arenas[narenas]; + ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas]; ctl_arena_clear(astats); -#ifdef JEMALLOC_STATS - ctl_arena_stats_amerge(astats, arena); - /* Merge into sum stats as well. */ - ctl_arena_stats_smerge(sstats, astats); -#else - astats->pactive += arena->nactive; - astats->pdirty += arena->ndirty; - /* Merge into sum stats as well. */ - sstats->pactive += arena->nactive; - sstats->pdirty += arena->ndirty; -#endif + sstats->nthreads += astats->nthreads; + if (config_stats) { + ctl_arena_stats_amerge(astats, arena); + /* Merge into sum stats as well. */ + ctl_arena_stats_smerge(sstats, astats); + } else { + astats->pactive += arena->nactive; + astats->pdirty += arena->ndirty; + /* Merge into sum stats as well. */ + sstats->pactive += arena->nactive; + sstats->pdirty += arena->ndirty; + } +} + +static bool +ctl_grow(void) +{ + size_t astats_size; + ctl_arena_stats_t *astats; + arena_t **tarenas; + + /* Extend arena stats and arenas arrays. */ + astats_size = (ctl_stats.narenas + 2) * sizeof(ctl_arena_stats_t); + if (ctl_stats.narenas == narenas_auto) { + /* ctl_stats.arenas and arenas came from base_alloc(). */ + astats = (ctl_arena_stats_t *)imalloc(astats_size); + if (astats == NULL) + return (true); + memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) * + sizeof(ctl_arena_stats_t)); + + tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) * + sizeof(arena_t *)); + if (tarenas == NULL) { + idalloc(astats); + return (true); + } + memcpy(tarenas, arenas, ctl_stats.narenas * sizeof(arena_t *)); + } else { + astats = (ctl_arena_stats_t *)iralloc(ctl_stats.arenas, + astats_size, 0, 0, false, false); + if (astats == NULL) + return (true); + + tarenas = (arena_t **)iralloc(arenas, (ctl_stats.narenas + 1) * + sizeof(arena_t *), 0, 0, false, false); + if (tarenas == NULL) + return (true); + } + /* Initialize the new astats and arenas elements. */ + memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); + if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) + return (true); + tarenas[ctl_stats.narenas] = NULL; + /* Swap merged stats to their new location. */ + { + ctl_arena_stats_t tstats; + memcpy(&tstats, &astats[ctl_stats.narenas], + sizeof(ctl_arena_stats_t)); + memcpy(&astats[ctl_stats.narenas], + &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); + memcpy(&astats[ctl_stats.narenas + 1], &tstats, + sizeof(ctl_arena_stats_t)); + } + ctl_stats.arenas = astats; + ctl_stats.narenas++; + malloc_mutex_lock(&arenas_lock); + arenas = tarenas; + narenas_total++; + arenas_extend(narenas_total - 1); + malloc_mutex_unlock(&arenas_lock); + + return (false); } static void ctl_refresh(void) { unsigned i; - arena_t *tarenas[narenas]; - -#ifdef JEMALLOC_STATS - malloc_mutex_lock(&chunks_mtx); - ctl_stats.chunks.current = stats_chunks.curchunks; - ctl_stats.chunks.total = stats_chunks.nchunks; - ctl_stats.chunks.high = stats_chunks.highchunks; - malloc_mutex_unlock(&chunks_mtx); - - malloc_mutex_lock(&huge_mtx); - ctl_stats.huge.allocated = huge_allocated; - ctl_stats.huge.nmalloc = huge_nmalloc; - ctl_stats.huge.ndalloc = huge_ndalloc; - malloc_mutex_unlock(&huge_mtx); -#endif + VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); + + if (config_stats) { + malloc_mutex_lock(&chunks_mtx); + ctl_stats.chunks.current = stats_chunks.curchunks; + ctl_stats.chunks.total = stats_chunks.nchunks; + ctl_stats.chunks.high = stats_chunks.highchunks; + malloc_mutex_unlock(&chunks_mtx); + + malloc_mutex_lock(&huge_mtx); + ctl_stats.huge.allocated = huge_allocated; + ctl_stats.huge.nmalloc = huge_nmalloc; + ctl_stats.huge.ndalloc = huge_ndalloc; + malloc_mutex_unlock(&huge_mtx); + } /* * Clear sum stats, since they will be merged into by * ctl_arena_refresh(). */ - ctl_arena_clear(&ctl_stats.arenas[narenas]); + ctl_stats.arenas[ctl_stats.narenas].nthreads = 0; + ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]); malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * narenas); + memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); + for (i = 0; i < ctl_stats.narenas; i++) { + if (arenas[i] != NULL) + ctl_stats.arenas[i].nthreads = arenas[i]->nthreads; + else + ctl_stats.arenas[i].nthreads = 0; + } malloc_mutex_unlock(&arenas_lock); - for (i = 0; i < narenas; i++) { + for (i = 0; i < ctl_stats.narenas; i++) { bool initialized = (tarenas[i] != NULL); ctl_stats.arenas[i].initialized = initialized; @@ -670,20 +648,16 @@ ctl_refresh(void) ctl_arena_refresh(tarenas[i], i); } -#ifdef JEMALLOC_STATS - ctl_stats.allocated = ctl_stats.arenas[narenas].allocated_small - + ctl_stats.arenas[narenas].astats.allocated_large - + ctl_stats.huge.allocated; - ctl_stats.active = (ctl_stats.arenas[narenas].pactive << PAGE_SHIFT) - + ctl_stats.huge.allocated; - ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk); - -# ifdef JEMALLOC_SWAP - malloc_mutex_lock(&swap_mtx); - ctl_stats.swap_avail = swap_avail; - malloc_mutex_unlock(&swap_mtx); -# endif -#endif + if (config_stats) { + ctl_stats.allocated = + ctl_stats.arenas[ctl_stats.narenas].allocated_small + + ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large + + ctl_stats.huge.allocated; + ctl_stats.active = + (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE) + + ctl_stats.huge.allocated; + ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk); + } ctl_epoch++; } @@ -695,21 +669,19 @@ ctl_init(void) malloc_mutex_lock(&ctl_mtx); if (ctl_initialized == false) { -#ifdef JEMALLOC_STATS - unsigned i; -#endif - /* * Allocate space for one extra arena stats element, which * contains summed stats across all arenas. */ + assert(narenas_auto == narenas_total_get()); + ctl_stats.narenas = narenas_auto; ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( - (narenas + 1) * sizeof(ctl_arena_stats_t)); + (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); if (ctl_stats.arenas == NULL) { ret = true; - goto RETURN; + goto label_return; } - memset(ctl_stats.arenas, 0, (narenas + 1) * + memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); /* @@ -717,15 +689,16 @@ ctl_init(void) * ever get used. Lazy initialization would allow errors to * cause inconsistent state to be viewable by the application. */ -#ifdef JEMALLOC_STATS - for (i = 0; i <= narenas; i++) { - if (ctl_arena_init(&ctl_stats.arenas[i])) { - ret = true; - goto RETURN; + if (config_stats) { + unsigned i; + for (i = 0; i <= ctl_stats.narenas; i++) { + if (ctl_arena_init(&ctl_stats.arenas[i])) { + ret = true; + goto label_return; + } } } -#endif - ctl_stats.arenas[narenas].initialized = true; + ctl_stats.arenas[ctl_stats.narenas].initialized = true; ctl_epoch = 0; ctl_refresh(); @@ -733,7 +706,7 @@ ctl_init(void) } ret = false; -RETURN: +label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } @@ -745,7 +718,7 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, int ret; const char *elm, *tdot, *dot; size_t elen, i, j; - const ctl_node_t *node; + const ctl_named_node_t *node; elm = name; /* Equivalent to strchrnul(). */ @@ -753,54 +726,53 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, elen = (size_t)((uintptr_t)dot - (uintptr_t)elm); if (elen == 0) { ret = ENOENT; - goto RETURN; + goto label_return; } node = super_root_node; for (i = 0; i < *depthp; i++) { - assert(node->named); - assert(node->u.named.nchildren > 0); - if (node->u.named.children[0].named) { - const ctl_node_t *pnode = node; + assert(node); + assert(node->nchildren > 0); + if (ctl_named_node(node->children) != NULL) { + const ctl_named_node_t *pnode = node; /* Children are named. */ - for (j = 0; j < node->u.named.nchildren; j++) { - const ctl_node_t *child = - &node->u.named.children[j]; - if (strlen(child->u.named.name) == elen - && strncmp(elm, child->u.named.name, - elen) == 0) { + for (j = 0; j < node->nchildren; j++) { + const ctl_named_node_t *child = + ctl_named_children(node, j); + if (strlen(child->name) == elen && + strncmp(elm, child->name, elen) == 0) { node = child; if (nodesp != NULL) - nodesp[i] = node; + nodesp[i] = + (const ctl_node_t *)node; mibp[i] = j; break; } } if (node == pnode) { ret = ENOENT; - goto RETURN; + goto label_return; } } else { - unsigned long index; - const ctl_node_t *inode; + uintmax_t index; + const ctl_indexed_node_t *inode; /* Children are indexed. */ - index = strtoul(elm, NULL, 10); - if (index == ULONG_MAX) { + index = malloc_strtoumax(elm, NULL, 10); + if (index == UINTMAX_MAX || index > SIZE_T_MAX) { ret = ENOENT; - goto RETURN; + goto label_return; } - inode = &node->u.named.children[0]; - node = inode->u.indexed.index(mibp, *depthp, - index); + inode = ctl_indexed_node(node->children); + node = inode->index(mibp, *depthp, (size_t)index); if (node == NULL) { ret = ENOENT; - goto RETURN; + goto label_return; } if (nodesp != NULL) - nodesp[i] = node; + nodesp[i] = (const ctl_node_t *)node; mibp[i] = (size_t)index; } @@ -812,7 +784,7 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, * in this path through the tree. */ ret = ENOENT; - goto RETURN; + goto label_return; } /* Complete lookup successful. */ *depthp = i + 1; @@ -823,7 +795,7 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, if (*dot == '\0') { /* No more elements. */ ret = ENOENT; - goto RETURN; + goto label_return; } elm = &dot[1]; dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : @@ -832,7 +804,7 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, } ret = 0; -RETURN: +label_return: return (ret); } @@ -844,25 +816,27 @@ ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t depth; ctl_node_t const *nodes[CTL_MAX_DEPTH]; size_t mib[CTL_MAX_DEPTH]; + const ctl_named_node_t *node; if (ctl_initialized == false && ctl_init()) { ret = EAGAIN; - goto RETURN; + goto label_return; } depth = CTL_MAX_DEPTH; ret = ctl_lookup(name, nodes, mib, &depth); if (ret != 0) - goto RETURN; + goto label_return; - if (nodes[depth-1]->ctl == NULL) { + node = ctl_named_node(nodes[depth-1]); + if (node != NULL && node->ctl) + ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen); + else { /* The name refers to a partial path through the ctl tree. */ ret = ENOENT; - goto RETURN; } - ret = nodes[depth-1]->ctl(mib, depth, oldp, oldlenp, newp, newlen); -RETURN: +label_return: return(ret); } @@ -873,11 +847,11 @@ ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp) if (ctl_initialized == false && ctl_init()) { ret = EAGAIN; - goto RETURN; + goto label_return; } ret = ctl_lookup(name, NULL, mibp, miblenp); -RETURN: +label_return: return(ret); } @@ -886,46 +860,48 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - const ctl_node_t *node; + const ctl_named_node_t *node; size_t i; if (ctl_initialized == false && ctl_init()) { ret = EAGAIN; - goto RETURN; + goto label_return; } /* Iterate down the tree. */ node = super_root_node; for (i = 0; i < miblen; i++) { - if (node->u.named.children[0].named) { + assert(node); + assert(node->nchildren > 0); + if (ctl_named_node(node->children) != NULL) { /* Children are named. */ - if (node->u.named.nchildren <= mib[i]) { + if (node->nchildren <= mib[i]) { ret = ENOENT; - goto RETURN; + goto label_return; } - node = &node->u.named.children[mib[i]]; + node = ctl_named_children(node, mib[i]); } else { - const ctl_node_t *inode; + const ctl_indexed_node_t *inode; /* Indexed element. */ - inode = &node->u.named.children[0]; - node = inode->u.indexed.index(mib, miblen, mib[i]); + inode = ctl_indexed_node(node->children); + node = inode->index(mib, miblen, mib[i]); if (node == NULL) { ret = ENOENT; - goto RETURN; + goto label_return; } } } /* Call the ctl function. */ - if (node->ctl == NULL) { + if (node && node->ctl) + ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen); + else { /* Partial MIB. */ ret = ENOENT; - goto RETURN; } - ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen); -RETURN: +label_return: return(ret); } @@ -941,38 +917,54 @@ ctl_boot(void) return (false); } +void +ctl_prefork(void) +{ + + malloc_mutex_lock(&ctl_mtx); +} + +void +ctl_postfork_parent(void) +{ + + malloc_mutex_postfork_parent(&ctl_mtx); +} + +void +ctl_postfork_child(void) +{ + + malloc_mutex_postfork_child(&ctl_mtx); +} + /******************************************************************************/ /* *_ctl() functions. */ #define READONLY() do { \ if (newp != NULL || newlen != 0) { \ ret = EPERM; \ - goto RETURN; \ + goto label_return; \ } \ } while (0) #define WRITEONLY() do { \ if (oldp != NULL || oldlenp != NULL) { \ ret = EPERM; \ - goto RETURN; \ + goto label_return; \ } \ } while (0) -#define VOID() do { \ - READONLY(); \ - WRITEONLY(); \ -} while (0) - #define READ(v, t) do { \ if (oldp != NULL && oldlenp != NULL) { \ if (*oldlenp != sizeof(t)) { \ size_t copylen = (sizeof(t) <= *oldlenp) \ ? sizeof(t) : *oldlenp; \ - memcpy(oldp, (void *)&v, copylen); \ + memcpy(oldp, (void *)&(v), copylen); \ ret = EINVAL; \ - goto RETURN; \ + goto label_return; \ } else \ - *(t *)oldp = v; \ + *(t *)oldp = (v); \ } \ } while (0) @@ -980,12 +972,60 @@ ctl_boot(void) if (newp != NULL) { \ if (newlen != sizeof(t)) { \ ret = EINVAL; \ - goto RETURN; \ + goto label_return; \ } \ - v = *(t *)newp; \ + (v) = *(t *)newp; \ } \ } while (0) +/* + * There's a lot of code duplication in the following macros due to limitations + * in how nested cpp macros are expanded. + */ +#define CTL_RO_CLGEN(c, l, n, v, t) \ +static int \ +n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ + void *newp, size_t newlen) \ +{ \ + int ret; \ + t oldval; \ + \ + if ((c) == false) \ + return (ENOENT); \ + if (l) \ + malloc_mutex_lock(&ctl_mtx); \ + READONLY(); \ + oldval = (v); \ + READ(oldval, t); \ + \ + ret = 0; \ +label_return: \ + if (l) \ + malloc_mutex_unlock(&ctl_mtx); \ + return (ret); \ +} + +#define CTL_RO_CGEN(c, n, v, t) \ +static int \ +n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ + void *newp, size_t newlen) \ +{ \ + int ret; \ + t oldval; \ + \ + if ((c) == false) \ + return (ENOENT); \ + malloc_mutex_lock(&ctl_mtx); \ + READONLY(); \ + oldval = (v); \ + READ(oldval, t); \ + \ + ret = 0; \ +label_return: \ + malloc_mutex_unlock(&ctl_mtx); \ + return (ret); \ +} + #define CTL_RO_GEN(n, v, t) \ static int \ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ @@ -996,11 +1036,11 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ \ malloc_mutex_lock(&ctl_mtx); \ READONLY(); \ - oldval = v; \ + oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ -RETURN: \ +label_return: \ malloc_mutex_unlock(&ctl_mtx); \ return (ret); \ } @@ -1009,7 +1049,7 @@ RETURN: \ * ctl_mtx is not acquired, under the assumption that no pertinent data will * mutate during the call. */ -#define CTL_RO_NL_GEN(n, v, t) \ +#define CTL_RO_NL_CGEN(c, n, v, t) \ static int \ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ void *newp, size_t newlen) \ @@ -1017,33 +1057,35 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ int ret; \ t oldval; \ \ + if ((c) == false) \ + return (ENOENT); \ READONLY(); \ - oldval = v; \ + oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ -RETURN: \ +label_return: \ return (ret); \ } -#define CTL_RO_TRUE_GEN(n) \ +#define CTL_RO_NL_GEN(n, v, t) \ static int \ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ void *newp, size_t newlen) \ { \ int ret; \ - bool oldval; \ + t oldval; \ \ READONLY(); \ - oldval = true; \ - READ(oldval, bool); \ + oldval = (v); \ + READ(oldval, t); \ \ ret = 0; \ -RETURN: \ +label_return: \ return (ret); \ } -#define CTL_RO_FALSE_GEN(n) \ +#define CTL_RO_BOOL_CONFIG_GEN(n) \ static int \ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ void *newp, size_t newlen) \ @@ -1052,11 +1094,11 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ bool oldval; \ \ READONLY(); \ - oldval = false; \ + oldval = n; \ READ(oldval, bool); \ \ ret = 0; \ -RETURN: \ +label_return: \ return (ret); \ } @@ -1070,41 +1112,60 @@ epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, uint64_t newval; malloc_mutex_lock(&ctl_mtx); - newval = 0; WRITE(newval, uint64_t); - if (newval != 0) + if (newp != NULL) ctl_refresh(); READ(ctl_epoch, uint64_t); ret = 0; -RETURN: +label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } -#ifdef JEMALLOC_TCACHE static int -tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) +thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; - tcache_t *tcache; + bool oldval; - VOID(); + if (config_tcache == false) + return (ENOENT); - tcache = TCACHE_GET(); - if (tcache == NULL) { - ret = 0; - goto RETURN; + oldval = tcache_enabled_get(); + if (newp != NULL) { + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + tcache_enabled_set(*(bool *)newp); } - tcache_destroy(tcache); - TCACHE_SET(NULL); + READ(oldval, bool); ret = 0; -RETURN: +label_return: + return (ret); +} + +static int +thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) +{ + int ret; + + if (config_tcache == false) + return (ENOENT); + + READONLY(); + WRITEONLY(); + + tcache_flush(); + + ret = 0; +label_return: return (ret); } -#endif static int thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, @@ -1113,191 +1174,231 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, int ret; unsigned newind, oldind; - newind = oldind = choose_arena()->ind; - WRITE(oldind, unsigned); - READ(newind, unsigned); + malloc_mutex_lock(&ctl_mtx); + newind = oldind = choose_arena(NULL)->ind; + WRITE(newind, unsigned); + READ(oldind, unsigned); if (newind != oldind) { arena_t *arena; - if (newind >= narenas) { + if (newind >= ctl_stats.narenas) { /* New arena index is out of range. */ ret = EFAULT; - goto RETURN; + goto label_return; } /* Initialize arena if necessary. */ malloc_mutex_lock(&arenas_lock); - if ((arena = arenas[newind]) == NULL) - arena = arenas_extend(newind); - malloc_mutex_unlock(&arenas_lock); - if (arena == NULL) { + if ((arena = arenas[newind]) == NULL && (arena = + arenas_extend(newind)) == NULL) { + malloc_mutex_unlock(&arenas_lock); ret = EAGAIN; - goto RETURN; + goto label_return; } + assert(arena == arenas[newind]); + arenas[oldind]->nthreads--; + arenas[newind]->nthreads++; + malloc_mutex_unlock(&arenas_lock); /* Set new arena association. */ - ARENA_SET(arena); + if (config_tcache) { + tcache_t *tcache; + if ((uintptr_t)(tcache = *tcache_tsd_get()) > + (uintptr_t)TCACHE_STATE_MAX) { + tcache_arena_dissociate(tcache); + tcache_arena_associate(tcache, arena); + } + } + arenas_tsd_set(&arena); } ret = 0; -RETURN: +label_return: + malloc_mutex_unlock(&ctl_mtx); return (ret); } -#ifdef JEMALLOC_STATS -CTL_RO_NL_GEN(thread_allocated, ALLOCATED_GET(), uint64_t); -CTL_RO_NL_GEN(thread_allocatedp, &ALLOCATED_GET(), uint64_t *); -CTL_RO_NL_GEN(thread_deallocated, DEALLOCATED_GET(), uint64_t); -CTL_RO_NL_GEN(thread_deallocatedp, &DEALLOCATED_GET(), uint64_t *); -#endif +CTL_RO_NL_CGEN(config_stats, thread_allocated, + thread_allocated_tsd_get()->allocated, uint64_t) +CTL_RO_NL_CGEN(config_stats, thread_allocatedp, + &thread_allocated_tsd_get()->allocated, uint64_t *) +CTL_RO_NL_CGEN(config_stats, thread_deallocated, + thread_allocated_tsd_get()->deallocated, uint64_t) +CTL_RO_NL_CGEN(config_stats, thread_deallocatedp, + &thread_allocated_tsd_get()->deallocated, uint64_t *) /******************************************************************************/ -#ifdef JEMALLOC_DEBUG -CTL_RO_TRUE_GEN(config_debug) -#else -CTL_RO_FALSE_GEN(config_debug) -#endif - -#ifdef JEMALLOC_DSS -CTL_RO_TRUE_GEN(config_dss) -#else -CTL_RO_FALSE_GEN(config_dss) -#endif - -#ifdef JEMALLOC_DYNAMIC_PAGE_SHIFT -CTL_RO_TRUE_GEN(config_dynamic_page_shift) -#else -CTL_RO_FALSE_GEN(config_dynamic_page_shift) -#endif - -#ifdef JEMALLOC_FILL -CTL_RO_TRUE_GEN(config_fill) -#else -CTL_RO_FALSE_GEN(config_fill) -#endif - -#ifdef JEMALLOC_LAZY_LOCK -CTL_RO_TRUE_GEN(config_lazy_lock) -#else -CTL_RO_FALSE_GEN(config_lazy_lock) -#endif - -#ifdef JEMALLOC_PROF -CTL_RO_TRUE_GEN(config_prof) -#else -CTL_RO_FALSE_GEN(config_prof) -#endif - -#ifdef JEMALLOC_PROF_LIBGCC -CTL_RO_TRUE_GEN(config_prof_libgcc) -#else -CTL_RO_FALSE_GEN(config_prof_libgcc) -#endif - -#ifdef JEMALLOC_PROF_LIBUNWIND -CTL_RO_TRUE_GEN(config_prof_libunwind) -#else -CTL_RO_FALSE_GEN(config_prof_libunwind) -#endif - -#ifdef JEMALLOC_STATS -CTL_RO_TRUE_GEN(config_stats) -#else -CTL_RO_FALSE_GEN(config_stats) -#endif - -#ifdef JEMALLOC_SWAP -CTL_RO_TRUE_GEN(config_swap) -#else -CTL_RO_FALSE_GEN(config_swap) -#endif - -#ifdef JEMALLOC_SYSV -CTL_RO_TRUE_GEN(config_sysv) -#else -CTL_RO_FALSE_GEN(config_sysv) -#endif - -#ifdef JEMALLOC_TCACHE -CTL_RO_TRUE_GEN(config_tcache) -#else -CTL_RO_FALSE_GEN(config_tcache) -#endif - -#ifdef JEMALLOC_TINY -CTL_RO_TRUE_GEN(config_tiny) -#else -CTL_RO_FALSE_GEN(config_tiny) -#endif - -#ifdef JEMALLOC_TLS -CTL_RO_TRUE_GEN(config_tls) -#else -CTL_RO_FALSE_GEN(config_tls) -#endif - -#ifdef JEMALLOC_XMALLOC -CTL_RO_TRUE_GEN(config_xmalloc) -#else -CTL_RO_FALSE_GEN(config_xmalloc) -#endif +CTL_RO_BOOL_CONFIG_GEN(config_debug) +CTL_RO_BOOL_CONFIG_GEN(config_dss) +CTL_RO_BOOL_CONFIG_GEN(config_fill) +CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock) +CTL_RO_BOOL_CONFIG_GEN(config_mremap) +CTL_RO_BOOL_CONFIG_GEN(config_munmap) +CTL_RO_BOOL_CONFIG_GEN(config_prof) +CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc) +CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind) +CTL_RO_BOOL_CONFIG_GEN(config_stats) +CTL_RO_BOOL_CONFIG_GEN(config_tcache) +CTL_RO_BOOL_CONFIG_GEN(config_tls) +CTL_RO_BOOL_CONFIG_GEN(config_utrace) +CTL_RO_BOOL_CONFIG_GEN(config_valgrind) +CTL_RO_BOOL_CONFIG_GEN(config_xmalloc) /******************************************************************************/ CTL_RO_NL_GEN(opt_abort, opt_abort, bool) -CTL_RO_NL_GEN(opt_lg_qspace_max, opt_lg_qspace_max, size_t) -CTL_RO_NL_GEN(opt_lg_cspace_max, opt_lg_cspace_max, size_t) +CTL_RO_NL_GEN(opt_dss, opt_dss, const char *) CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t) CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t) CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t) CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool) -#ifdef JEMALLOC_FILL -CTL_RO_NL_GEN(opt_junk, opt_junk, bool) -CTL_RO_NL_GEN(opt_zero, opt_zero, bool) -#endif -#ifdef JEMALLOC_SYSV -CTL_RO_NL_GEN(opt_sysv, opt_sysv, bool) -#endif -#ifdef JEMALLOC_XMALLOC -CTL_RO_NL_GEN(opt_xmalloc, opt_xmalloc, bool) -#endif -#ifdef JEMALLOC_TCACHE -CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool) -CTL_RO_NL_GEN(opt_lg_tcache_gc_sweep, opt_lg_tcache_gc_sweep, ssize_t) -#endif -#ifdef JEMALLOC_PROF -CTL_RO_NL_GEN(opt_prof, opt_prof, bool) -CTL_RO_NL_GEN(opt_prof_prefix, opt_prof_prefix, const char *) -CTL_RO_GEN(opt_prof_active, opt_prof_active, bool) /* Mutable. */ -CTL_RO_NL_GEN(opt_lg_prof_bt_max, opt_lg_prof_bt_max, size_t) -CTL_RO_NL_GEN(opt_lg_prof_sample, opt_lg_prof_sample, size_t) -CTL_RO_NL_GEN(opt_lg_prof_interval, opt_lg_prof_interval, ssize_t) -CTL_RO_NL_GEN(opt_prof_gdump, opt_prof_gdump, bool) -CTL_RO_NL_GEN(opt_prof_leak, opt_prof_leak, bool) -CTL_RO_NL_GEN(opt_prof_accum, opt_prof_accum, bool) -CTL_RO_NL_GEN(opt_lg_prof_tcmax, opt_lg_prof_tcmax, ssize_t) -#endif -#ifdef JEMALLOC_SWAP -CTL_RO_NL_GEN(opt_overcommit, opt_overcommit, bool) -#endif +CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool) +CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) +CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t) +CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool) +CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool) +CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool) +CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool) +CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool) +CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) +CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *) +CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */ +CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t) +CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t) +CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool) /******************************************************************************/ -CTL_RO_NL_GEN(arenas_bin_i_size, arenas[0]->bins[mib[2]].reg_size, size_t) -CTL_RO_NL_GEN(arenas_bin_i_nregs, arenas[0]->bins[mib[2]].nregs, uint32_t) -CTL_RO_NL_GEN(arenas_bin_i_run_size, arenas[0]->bins[mib[2]].run_size, size_t) -const ctl_node_t * +/* ctl_mutex must be held during execution of this function. */ +static void +arena_purge(unsigned arena_ind) +{ + VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); + + malloc_mutex_lock(&arenas_lock); + memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); + malloc_mutex_unlock(&arenas_lock); + + if (arena_ind == ctl_stats.narenas) { + unsigned i; + for (i = 0; i < ctl_stats.narenas; i++) { + if (tarenas[i] != NULL) + arena_purge_all(tarenas[i]); + } + } else { + assert(arena_ind < ctl_stats.narenas); + if (tarenas[arena_ind] != NULL) + arena_purge_all(tarenas[arena_ind]); + } +} + +static int +arena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int ret; + + READONLY(); + WRITEONLY(); + malloc_mutex_lock(&ctl_mtx); + arena_purge(mib[1]); + malloc_mutex_unlock(&ctl_mtx); + + ret = 0; +label_return: + return (ret); +} + +static int +arena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int ret, i; + bool match, err; + const char *dss; + unsigned arena_ind = mib[1]; + dss_prec_t dss_prec_old = dss_prec_limit; + dss_prec_t dss_prec = dss_prec_limit; + + malloc_mutex_lock(&ctl_mtx); + WRITE(dss, const char *); + match = false; + for (i = 0; i < dss_prec_limit; i++) { + if (strcmp(dss_prec_names[i], dss) == 0) { + dss_prec = i; + match = true; + break; + } + } + if (match == false) { + ret = EINVAL; + goto label_return; + } + + if (arena_ind < ctl_stats.narenas) { + arena_t *arena = arenas[arena_ind]; + if (arena != NULL) { + dss_prec_old = arena_dss_prec_get(arena); + arena_dss_prec_set(arena, dss_prec); + err = false; + } else + err = true; + } else { + dss_prec_old = chunk_dss_prec_get(); + err = chunk_dss_prec_set(dss_prec); + } + dss = dss_prec_names[dss_prec_old]; + READ(dss, const char *); + if (err) { + ret = EFAULT; + goto label_return; + } + + ret = 0; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} + +static const ctl_named_node_t * +arena_i_index(const size_t *mib, size_t miblen, size_t i) +{ + const ctl_named_node_t * ret; + + malloc_mutex_lock(&ctl_mtx); + if (i > ctl_stats.narenas) { + ret = NULL; + goto label_return; + } + + ret = super_arena_i_node; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} + + +/******************************************************************************/ + +CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t) +CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t) +static const ctl_named_node_t * arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i) { - if (i > nbins) + if (i > NBINS) return (NULL); return (super_arenas_bin_i_node); } -CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << PAGE_SHIFT), size_t) -const ctl_node_t * +CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t) +static const ctl_named_node_t * arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) { @@ -1306,7 +1407,27 @@ arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) return (super_arenas_lrun_i_node); } -CTL_RO_NL_GEN(arenas_narenas, narenas, unsigned) +static int +arenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) +{ + int ret; + unsigned narenas; + + malloc_mutex_lock(&ctl_mtx); + READONLY(); + if (*oldlenp != sizeof(unsigned)) { + ret = EINVAL; + goto label_return; + } + narenas = ctl_stats.narenas; + READ(narenas, unsigned); + + ret = 0; +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} static int arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp, @@ -1317,49 +1438,28 @@ arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp, malloc_mutex_lock(&ctl_mtx); READONLY(); - if (*oldlenp != narenas * sizeof(bool)) { + if (*oldlenp != ctl_stats.narenas * sizeof(bool)) { ret = EINVAL; - nread = (*oldlenp < narenas * sizeof(bool)) - ? (*oldlenp / sizeof(bool)) : narenas; + nread = (*oldlenp < ctl_stats.narenas * sizeof(bool)) + ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas; } else { ret = 0; - nread = narenas; + nread = ctl_stats.narenas; } for (i = 0; i < nread; i++) ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized; -RETURN: +label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t) -CTL_RO_NL_GEN(arenas_cacheline, CACHELINE, size_t) -CTL_RO_NL_GEN(arenas_subpage, SUBPAGE, size_t) -CTL_RO_NL_GEN(arenas_pagesize, PAGE_SIZE, size_t) -CTL_RO_NL_GEN(arenas_chunksize, chunksize, size_t) -#ifdef JEMALLOC_TINY -CTL_RO_NL_GEN(arenas_tspace_min, (1U << LG_TINY_MIN), size_t) -CTL_RO_NL_GEN(arenas_tspace_max, (qspace_min >> 1), size_t) -#endif -CTL_RO_NL_GEN(arenas_qspace_min, qspace_min, size_t) -CTL_RO_NL_GEN(arenas_qspace_max, qspace_max, size_t) -CTL_RO_NL_GEN(arenas_cspace_min, cspace_min, size_t) -CTL_RO_NL_GEN(arenas_cspace_max, cspace_max, size_t) -CTL_RO_NL_GEN(arenas_sspace_min, sspace_min, size_t) -CTL_RO_NL_GEN(arenas_sspace_max, sspace_max, size_t) -#ifdef JEMALLOC_TCACHE -CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t) -#endif -CTL_RO_NL_GEN(arenas_ntbins, ntbins, unsigned) -CTL_RO_NL_GEN(arenas_nqbins, nqbins, unsigned) -CTL_RO_NL_GEN(arenas_ncbins, ncbins, unsigned) -CTL_RO_NL_GEN(arenas_nsbins, nsbins, unsigned) -CTL_RO_NL_GEN(arenas_nbins, nbins, unsigned) -#ifdef JEMALLOC_TCACHE -CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned) -#endif +CTL_RO_NL_GEN(arenas_page, PAGE, size_t) +CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t) +CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned) +CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned) CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t) static int @@ -1367,42 +1467,50 @@ arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - unsigned arena; + unsigned arena_ind; + malloc_mutex_lock(&ctl_mtx); WRITEONLY(); - arena = UINT_MAX; - WRITE(arena, unsigned); - if (newp != NULL && arena >= narenas) { + arena_ind = UINT_MAX; + WRITE(arena_ind, unsigned); + if (newp != NULL && arena_ind >= ctl_stats.narenas) ret = EFAULT; - goto RETURN; - } else { - arena_t *tarenas[narenas]; + else { + if (arena_ind == UINT_MAX) + arena_ind = ctl_stats.narenas; + arena_purge(arena_ind); + ret = 0; + } - malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * narenas); - malloc_mutex_unlock(&arenas_lock); +label_return: + malloc_mutex_unlock(&ctl_mtx); + return (ret); +} - if (arena == UINT_MAX) { - unsigned i; - for (i = 0; i < narenas; i++) { - if (tarenas[i] != NULL) - arena_purge_all(tarenas[i]); - } - } else { - assert(arena < narenas); - if (tarenas[arena] != NULL) - arena_purge_all(tarenas[arena]); - } +static int +arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) +{ + int ret; + unsigned narenas; + + malloc_mutex_lock(&ctl_mtx); + READONLY(); + if (ctl_grow()) { + ret = EAGAIN; + goto label_return; } + narenas = ctl_stats.narenas - 1; + READ(narenas, unsigned); ret = 0; -RETURN: +label_return: + malloc_mutex_unlock(&ctl_mtx); return (ret); } /******************************************************************************/ -#ifdef JEMALLOC_PROF static int prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) @@ -1410,6 +1518,9 @@ prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, int ret; bool oldval; + if (config_prof == false) + return (ENOENT); + malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */ oldval = opt_prof_active; if (newp != NULL) { @@ -1424,7 +1535,7 @@ prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, READ(oldval, bool); ret = 0; -RETURN: +label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } @@ -1436,92 +1547,88 @@ prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, int ret; const char *filename = NULL; + if (config_prof == false) + return (ENOENT); + WRITEONLY(); WRITE(filename, const char *); if (prof_mdump(filename)) { ret = EFAULT; - goto RETURN; + goto label_return; } ret = 0; -RETURN: +label_return: return (ret); } -CTL_RO_NL_GEN(prof_interval, prof_interval, uint64_t) -#endif +CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t) /******************************************************************************/ -#ifdef JEMALLOC_STATS -CTL_RO_GEN(stats_chunks_current, ctl_stats.chunks.current, size_t) -CTL_RO_GEN(stats_chunks_total, ctl_stats.chunks.total, uint64_t) -CTL_RO_GEN(stats_chunks_high, ctl_stats.chunks.high, size_t) -CTL_RO_GEN(stats_huge_allocated, huge_allocated, size_t) -CTL_RO_GEN(stats_huge_nmalloc, huge_nmalloc, uint64_t) -CTL_RO_GEN(stats_huge_ndalloc, huge_ndalloc, uint64_t) -CTL_RO_GEN(stats_arenas_i_small_allocated, +CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current, + size_t) +CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t) +CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t) +CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t) +CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t) +CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated, ctl_stats.arenas[mib[2]].allocated_small, size_t) -CTL_RO_GEN(stats_arenas_i_small_nmalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc, ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t) -CTL_RO_GEN(stats_arenas_i_small_ndalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc, ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t) -CTL_RO_GEN(stats_arenas_i_small_nrequests, +CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests, ctl_stats.arenas[mib[2]].nrequests_small, uint64_t) -CTL_RO_GEN(stats_arenas_i_large_allocated, +CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated, ctl_stats.arenas[mib[2]].astats.allocated_large, size_t) -CTL_RO_GEN(stats_arenas_i_large_nmalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc, ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t) -CTL_RO_GEN(stats_arenas_i_large_ndalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc, ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t) -CTL_RO_GEN(stats_arenas_i_large_nrequests, +CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests, ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_allocated, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated, ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t) -CTL_RO_GEN(stats_arenas_i_bins_j_nmalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc, ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_ndalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc, ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_nrequests, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests, ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t) -#ifdef JEMALLOC_TCACHE -CTL_RO_GEN(stats_arenas_i_bins_j_nfills, +CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills, ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_nflushes, +CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes, ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t) -#endif -CTL_RO_GEN(stats_arenas_i_bins_j_nruns, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns, ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_nreruns, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns, ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t) -CTL_RO_GEN(stats_arenas_i_bins_j_highruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].highruns, size_t) -CTL_RO_GEN(stats_arenas_i_bins_j_curruns, +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns, ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t) -const ctl_node_t * +static const ctl_named_node_t * stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j) { - if (j > nbins) + if (j > NBINS) return (NULL); return (super_stats_arenas_i_bins_j_node); } -CTL_RO_GEN(stats_arenas_i_lruns_j_nmalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc, ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t) -CTL_RO_GEN(stats_arenas_i_lruns_j_ndalloc, +CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc, ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t) -CTL_RO_GEN(stats_arenas_i_lruns_j_nrequests, +CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests, ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t) -CTL_RO_GEN(stats_arenas_i_lruns_j_curruns, +CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns, ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t) -CTL_RO_GEN(stats_arenas_i_lruns_j_highruns, - ctl_stats.arenas[mib[2]].lstats[mib[4]].highruns, size_t) -const ctl_node_t * +static const ctl_named_node_t * stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) { @@ -1530,118 +1637,37 @@ stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) return (super_stats_arenas_i_lruns_j_node); } -#endif +CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned) +CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *) CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t) CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t) -#ifdef JEMALLOC_STATS -CTL_RO_GEN(stats_arenas_i_mapped, ctl_stats.arenas[mib[2]].astats.mapped, - size_t) -CTL_RO_GEN(stats_arenas_i_npurge, ctl_stats.arenas[mib[2]].astats.npurge, - uint64_t) -CTL_RO_GEN(stats_arenas_i_nmadvise, ctl_stats.arenas[mib[2]].astats.nmadvise, - uint64_t) -CTL_RO_GEN(stats_arenas_i_purged, ctl_stats.arenas[mib[2]].astats.purged, - uint64_t) -#endif - -const ctl_node_t * +CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, + ctl_stats.arenas[mib[2]].astats.mapped, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_npurge, + ctl_stats.arenas[mib[2]].astats.npurge, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise, + ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_purged, + ctl_stats.arenas[mib[2]].astats.purged, uint64_t) + +static const ctl_named_node_t * stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i) { - const ctl_node_t * ret; + const ctl_named_node_t * ret; malloc_mutex_lock(&ctl_mtx); - if (ctl_stats.arenas[i].initialized == false) { + if (i > ctl_stats.narenas || ctl_stats.arenas[i].initialized == false) { ret = NULL; - goto RETURN; + goto label_return; } ret = super_stats_arenas_i_node; -RETURN: +label_return: malloc_mutex_unlock(&ctl_mtx); return (ret); } -#ifdef JEMALLOC_STATS -CTL_RO_GEN(stats_allocated, ctl_stats.allocated, size_t) -CTL_RO_GEN(stats_active, ctl_stats.active, size_t) -CTL_RO_GEN(stats_mapped, ctl_stats.mapped, size_t) -#endif - -/******************************************************************************/ - -#ifdef JEMALLOC_SWAP -# ifdef JEMALLOC_STATS -CTL_RO_GEN(swap_avail, ctl_stats.swap_avail, size_t) -# endif - -static int -swap_prezeroed_ctl(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) -{ - int ret; - - malloc_mutex_lock(&ctl_mtx); - if (swap_enabled) { - READONLY(); - } else { - /* - * swap_prezeroed isn't actually used by the swap code until it - * is set during a successful chunk_swap_enabled() call. We - * use it here to store the value that we'll pass to - * chunk_swap_enable() in a swap.fds mallctl(). This is not - * very clean, but the obvious alternatives are even worse. - */ - WRITE(swap_prezeroed, bool); - } - - READ(swap_prezeroed, bool); - - ret = 0; -RETURN: - malloc_mutex_unlock(&ctl_mtx); - return (ret); -} - -CTL_RO_GEN(swap_nfds, swap_nfds, size_t) - -static int -swap_fds_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ - int ret; - - malloc_mutex_lock(&ctl_mtx); - if (swap_enabled) { - READONLY(); - } else if (newp != NULL) { - size_t nfds = newlen / sizeof(int); - - { - int fds[nfds]; - - memcpy(fds, newp, nfds * sizeof(int)); - if (chunk_swap_enable(fds, nfds, swap_prezeroed)) { - ret = EFAULT; - goto RETURN; - } - } - } - - if (oldp != NULL && oldlenp != NULL) { - if (*oldlenp != swap_nfds * sizeof(int)) { - size_t copylen = (swap_nfds * sizeof(int) <= *oldlenp) - ? swap_nfds * sizeof(int) : *oldlenp; - - memcpy(oldp, swap_fds, copylen); - ret = EINVAL; - goto RETURN; - } else - memcpy(oldp, swap_fds, *oldlenp); - } - - ret = 0; -RETURN: - malloc_mutex_unlock(&ctl_mtx); - return (ret); -} -#endif +CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *) +CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t) +CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t) +CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t) diff --git a/dep/jemalloc/src/extent.c b/dep/jemalloc/src/extent.c index 3c04d3aa5d1..8c09b486ed8 100644 --- a/dep/jemalloc/src/extent.c +++ b/dep/jemalloc/src/extent.c @@ -3,7 +3,6 @@ /******************************************************************************/ -#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS)) static inline int extent_szad_comp(extent_node_t *a, extent_node_t *b) { @@ -25,7 +24,6 @@ extent_szad_comp(extent_node_t *a, extent_node_t *b) /* Generate red-black tree functions. */ rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, link_szad, extent_szad_comp) -#endif static inline int extent_ad_comp(extent_node_t *a, extent_node_t *b) diff --git a/dep/jemalloc/src/hash.c b/dep/jemalloc/src/hash.c index 6a13d7a03c0..cfa4da0275c 100644 --- a/dep/jemalloc/src/hash.c +++ b/dep/jemalloc/src/hash.c @@ -1,2 +1,2 @@ -#define HASH_C_ +#define JEMALLOC_HASH_C_ #include "jemalloc/internal/jemalloc_internal.h" diff --git a/dep/jemalloc/src/huge.c b/dep/jemalloc/src/huge.c index 0aadc4339a9..aa08d43d362 100644 --- a/dep/jemalloc/src/huge.c +++ b/dep/jemalloc/src/huge.c @@ -4,11 +4,9 @@ /******************************************************************************/ /* Data. */ -#ifdef JEMALLOC_STATS uint64_t huge_nmalloc; uint64_t huge_ndalloc; size_t huge_allocated; -#endif malloc_mutex_t huge_mtx; @@ -20,9 +18,17 @@ static extent_tree_t huge; void * huge_malloc(size_t size, bool zero) { + + return (huge_palloc(size, chunksize, zero)); +} + +void * +huge_palloc(size_t size, size_t alignment, bool zero) +{ void *ret; size_t csize; extent_node_t *node; + bool is_zeroed; /* Allocate one or more contiguous chunks for this request. */ @@ -37,7 +43,13 @@ huge_malloc(size_t size, bool zero) if (node == NULL) return (NULL); - ret = chunk_alloc(csize, false, &zero); + /* + * Copy zero into is_zeroed and pass the copy to chunk_alloc(), so that + * it is possible to make correct junk/zero fill decisions below. + */ + is_zeroed = zero; + ret = chunk_alloc(csize, alignment, false, &is_zeroed, + chunk_dss_prec_get()); if (ret == NULL) { base_node_dealloc(node); return (NULL); @@ -49,104 +61,19 @@ huge_malloc(size_t size, bool zero) malloc_mutex_lock(&huge_mtx); extent_tree_ad_insert(&huge, node); -#ifdef JEMALLOC_STATS - huge_nmalloc++; - huge_allocated += csize; -#endif + if (config_stats) { + stats_cactive_add(csize); + huge_nmalloc++; + huge_allocated += csize; + } malloc_mutex_unlock(&huge_mtx); -#ifdef JEMALLOC_FILL - if (zero == false) { + if (config_fill && zero == false) { if (opt_junk) memset(ret, 0xa5, csize); - else if (opt_zero) + else if (opt_zero && is_zeroed == false) memset(ret, 0, csize); } -#endif - - return (ret); -} - -/* Only handles large allocations that require more than chunk alignment. */ -void * -huge_palloc(size_t size, size_t alignment, bool zero) -{ - void *ret; - size_t alloc_size, chunk_size, offset; - extent_node_t *node; - - /* - * This allocation requires alignment that is even larger than chunk - * alignment. This means that huge_malloc() isn't good enough. - * - * Allocate almost twice as many chunks as are demanded by the size or - * alignment, in order to assure the alignment can be achieved, then - * unmap leading and trailing chunks. - */ - assert(alignment >= chunksize); - - chunk_size = CHUNK_CEILING(size); - - if (size >= alignment) - alloc_size = chunk_size + alignment - chunksize; - else - alloc_size = (alignment << 1) - chunksize; - - /* Allocate an extent node with which to track the chunk. */ - node = base_node_alloc(); - if (node == NULL) - return (NULL); - - ret = chunk_alloc(alloc_size, false, &zero); - if (ret == NULL) { - base_node_dealloc(node); - return (NULL); - } - - offset = (uintptr_t)ret & (alignment - 1); - assert((offset & chunksize_mask) == 0); - assert(offset < alloc_size); - if (offset == 0) { - /* Trim trailing space. */ - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), alloc_size - - chunk_size); - } else { - size_t trailsize; - - /* Trim leading space. */ - chunk_dealloc(ret, alignment - offset); - - ret = (void *)((uintptr_t)ret + (alignment - offset)); - - trailsize = alloc_size - (alignment - offset) - chunk_size; - if (trailsize != 0) { - /* Trim trailing space. */ - assert(trailsize < alloc_size); - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), - trailsize); - } - } - - /* Insert node into huge. */ - node->addr = ret; - node->size = chunk_size; - - malloc_mutex_lock(&huge_mtx); - extent_tree_ad_insert(&huge, node); -#ifdef JEMALLOC_STATS - huge_nmalloc++; - huge_allocated += chunk_size; -#endif - malloc_mutex_unlock(&huge_mtx); - -#ifdef JEMALLOC_FILL - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, chunk_size); - else if (opt_zero) - memset(ret, 0, chunk_size); - } -#endif return (ret); } @@ -162,12 +89,10 @@ huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra) && CHUNK_CEILING(oldsize) >= CHUNK_CEILING(size) && CHUNK_CEILING(oldsize) <= CHUNK_CEILING(size+extra)) { assert(CHUNK_CEILING(oldsize) == oldsize); -#ifdef JEMALLOC_FILL - if (opt_junk && size < oldsize) { + if (config_fill && opt_junk && size < oldsize) { memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); } -#endif return (ptr); } @@ -177,7 +102,7 @@ huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra) void * huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, - size_t alignment, bool zero) + size_t alignment, bool zero, bool try_tcache_dalloc) { void *ret; size_t copysize; @@ -192,7 +117,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, * different size class. In that case, fall back to allocating new * space and copying. */ - if (alignment != 0) + if (alignment > chunksize) ret = huge_palloc(size + extra, alignment, zero); else ret = huge_malloc(size + extra, zero); @@ -201,7 +126,7 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, if (extra == 0) return (NULL); /* Try again, this time without extra. */ - if (alignment != 0) + if (alignment > chunksize) ret = huge_palloc(size, alignment, zero); else ret = huge_malloc(size, zero); @@ -216,22 +141,22 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, */ copysize = (size < oldsize) ? size : oldsize; +#ifdef JEMALLOC_MREMAP /* * Use mremap(2) if this is a huge-->huge reallocation, and neither the - * source nor the destination are in swap or dss. + * source nor the destination are in dss. */ -#ifdef JEMALLOC_MREMAP_FIXED - if (oldsize >= chunksize -# ifdef JEMALLOC_SWAP - && (swap_enabled == false || (chunk_in_swap(ptr) == false && - chunk_in_swap(ret) == false)) -# endif -# ifdef JEMALLOC_DSS - && chunk_in_dss(ptr) == false && chunk_in_dss(ret) == false -# endif - ) { + if (oldsize >= chunksize && (config_dss == false || (chunk_in_dss(ptr) + == false && chunk_in_dss(ret) == false))) { size_t newsize = huge_salloc(ret); + /* + * Remove ptr from the tree of huge allocations before + * performing the remap operation, in order to avoid the + * possibility of another thread acquiring that mapping before + * this one removes it from the tree. + */ + huge_dalloc(ptr, false); if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED, ret) == MAP_FAILED) { /* @@ -244,21 +169,19 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, */ char buf[BUFERROR_BUF]; - buferror(errno, buf, sizeof(buf)); - malloc_write("<jemalloc>: Error in mremap(): "); - malloc_write(buf); - malloc_write("\n"); + buferror(buf, sizeof(buf)); + malloc_printf("<jemalloc>: Error in mremap(): %s\n", + buf); if (opt_abort) abort(); memcpy(ret, ptr, copysize); - idalloc(ptr); - } else - huge_dalloc(ptr, false); + chunk_dealloc_mmap(ptr, oldsize); + } } else #endif { memcpy(ret, ptr, copysize); - idalloc(ptr); + iqallocx(ptr, try_tcache_dalloc); } return (ret); } @@ -277,23 +200,18 @@ huge_dalloc(void *ptr, bool unmap) assert(node->addr == ptr); extent_tree_ad_remove(&huge, node); -#ifdef JEMALLOC_STATS - huge_ndalloc++; - huge_allocated -= node->size; -#endif + if (config_stats) { + stats_cactive_sub(node->size); + huge_ndalloc++; + huge_allocated -= node->size; + } malloc_mutex_unlock(&huge_mtx); - if (unmap) { - /* Unmap chunk. */ -#ifdef JEMALLOC_FILL -#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS)) - if (opt_junk) - memset(node->addr, 0x5a, node->size); -#endif -#endif - chunk_dealloc(node->addr, node->size); - } + if (unmap && config_fill && config_dss && opt_junk) + memset(node->addr, 0x5a, node->size); + + chunk_dealloc(node->addr, node->size, unmap); base_node_dealloc(node); } @@ -318,7 +236,6 @@ huge_salloc(const void *ptr) return (ret); } -#ifdef JEMALLOC_PROF prof_ctx_t * huge_prof_ctx_get(const void *ptr) { @@ -355,7 +272,6 @@ huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx) malloc_mutex_unlock(&huge_mtx); } -#endif bool huge_boot(void) @@ -366,11 +282,32 @@ huge_boot(void) return (true); extent_tree_ad_new(&huge); -#ifdef JEMALLOC_STATS - huge_nmalloc = 0; - huge_ndalloc = 0; - huge_allocated = 0; -#endif + if (config_stats) { + huge_nmalloc = 0; + huge_ndalloc = 0; + huge_allocated = 0; + } return (false); } + +void +huge_prefork(void) +{ + + malloc_mutex_prefork(&huge_mtx); +} + +void +huge_postfork_parent(void) +{ + + malloc_mutex_postfork_parent(&huge_mtx); +} + +void +huge_postfork_child(void) +{ + + malloc_mutex_postfork_child(&huge_mtx); +} diff --git a/dep/jemalloc/src/jemalloc.c b/dep/jemalloc/src/jemalloc.c index 2aebc51dd19..bc350ed953b 100644 --- a/dep/jemalloc/src/jemalloc.c +++ b/dep/jemalloc/src/jemalloc.c @@ -4,105 +4,114 @@ /******************************************************************************/ /* Data. */ -malloc_mutex_t arenas_lock; -arena_t **arenas; -unsigned narenas; -static unsigned next_arena; +malloc_tsd_data(, arenas, arena_t *, NULL) +malloc_tsd_data(, thread_allocated, thread_allocated_t, + THREAD_ALLOCATED_INITIALIZER) -#ifndef NO_TLS -__thread arena_t *arenas_tls JEMALLOC_ATTR(tls_model("initial-exec")); +/* Runtime configuration options. */ +const char *je_malloc_conf; +bool opt_abort = +#ifdef JEMALLOC_DEBUG + true #else -pthread_key_t arenas_tsd; + false #endif - -#ifdef JEMALLOC_STATS -# ifndef NO_TLS -__thread thread_allocated_t thread_allocated_tls; -# else -pthread_key_t thread_allocated_tsd; -# endif + ; +bool opt_junk = +#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) + true +#else + false #endif + ; +size_t opt_quarantine = ZU(0); +bool opt_redzone = false; +bool opt_utrace = false; +bool opt_valgrind = false; +bool opt_xmalloc = false; +bool opt_zero = false; +size_t opt_narenas = 0; + +unsigned ncpus; + +malloc_mutex_t arenas_lock; +arena_t **arenas; +unsigned narenas_total; +unsigned narenas_auto; /* Set to true once the allocator has been initialized. */ static bool malloc_initialized = false; +#ifdef JEMALLOC_THREADED_INIT /* Used to let the initializing thread recursively allocate. */ -static pthread_t malloc_initializer = (unsigned long)0; +# define NO_INITIALIZER ((unsigned long)0) +# define INITIALIZER pthread_self() +# define IS_INITIALIZER (malloc_initializer == pthread_self()) +static pthread_t malloc_initializer = NO_INITIALIZER; +#else +# define NO_INITIALIZER false +# define INITIALIZER true +# define IS_INITIALIZER malloc_initializer +static bool malloc_initializer = NO_INITIALIZER; +#endif /* Used to avoid initialization races. */ -static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER; +#ifdef _WIN32 +static malloc_mutex_t init_lock; -#ifdef DYNAMIC_PAGE_SHIFT -size_t pagesize; -size_t pagesize_mask; -size_t lg_pagesize; -#endif +JEMALLOC_ATTR(constructor) +static void WINAPI +_init_init_lock(void) +{ -unsigned ncpus; + malloc_mutex_init(&init_lock); +} -/* Runtime configuration options. */ -const char *JEMALLOC_P(malloc_conf) JEMALLOC_ATTR(visibility("default")); -#ifdef JEMALLOC_DEBUG -bool opt_abort = true; -# ifdef JEMALLOC_FILL -bool opt_junk = true; -# endif -#else -bool opt_abort = false; -# ifdef JEMALLOC_FILL -bool opt_junk = false; -# endif -#endif -#ifdef JEMALLOC_SYSV -bool opt_sysv = false; +#ifdef _MSC_VER +# pragma section(".CRT$XCU", read) +JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used) +static const void (WINAPI *init_init_lock)(void) = _init_init_lock; #endif -#ifdef JEMALLOC_XMALLOC -bool opt_xmalloc = false; + +#else +static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER; #endif -#ifdef JEMALLOC_FILL -bool opt_zero = false; + +typedef struct { + void *p; /* Input pointer (as in realloc(p, s)). */ + size_t s; /* Request size. */ + void *r; /* Result pointer. */ +} malloc_utrace_t; + +#ifdef JEMALLOC_UTRACE +# define UTRACE(a, b, c) do { \ + if (opt_utrace) { \ + int utrace_serrno = errno; \ + malloc_utrace_t ut; \ + ut.p = (a); \ + ut.s = (b); \ + ut.r = (c); \ + utrace(&ut, sizeof(ut)); \ + errno = utrace_serrno; \ + } \ +} while (0) +#else +# define UTRACE(a, b, c) #endif -size_t opt_narenas = 0; /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -static void wrtmessage(void *cbopaque, const char *s); static void stats_print_atexit(void); static unsigned malloc_ncpus(void); -#if (defined(JEMALLOC_STATS) && defined(NO_TLS)) -static void thread_allocated_cleanup(void *arg); -#endif static bool malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, char const **v_p, size_t *vlen_p); static void malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, size_t vlen); static void malloc_conf_init(void); static bool malloc_init_hard(void); - -/******************************************************************************/ -/* malloc_message() setup. */ - -#ifdef JEMALLOC_HAVE_ATTR -JEMALLOC_ATTR(visibility("hidden")) -#else -static -#endif -void -wrtmessage(void *cbopaque, const char *s) -{ -#ifdef JEMALLOC_CC_SILENCE - int result = -#endif - write(STDERR_FILENO, s, strlen(s)); -#ifdef JEMALLOC_CC_SILENCE - if (result < 0) - result = errno; -#endif -} - -void (*JEMALLOC_P(malloc_message))(void *, const char *s) - JEMALLOC_ATTR(visibility("default")) = wrtmessage; +static int imemalign(void **memptr, size_t alignment, size_t size, + size_t min_alignment); /******************************************************************************/ /* @@ -115,9 +124,7 @@ arenas_extend(unsigned ind) { arena_t *ret; - /* Allocate enough space for trailing bins. */ - ret = (arena_t *)base_alloc(offsetof(arena_t, bins) - + (sizeof(arena_bin_t) * nbins)); + ret = (arena_t *)base_alloc(sizeof(arena_t)); if (ret != NULL && arena_new(ret, ind) == false) { arenas[ind] = ret; return (ret); @@ -137,80 +144,101 @@ arenas_extend(unsigned ind) return (arenas[0]); } -/* - * Choose an arena based on a per-thread value (slow-path code only, called - * only by choose_arena()). - */ +/* Slow path, called only by choose_arena(). */ arena_t * choose_arena_hard(void) { arena_t *ret; - if (narenas > 1) { + if (narenas_auto > 1) { + unsigned i, choose, first_null; + + choose = 0; + first_null = narenas_auto; malloc_mutex_lock(&arenas_lock); - if ((ret = arenas[next_arena]) == NULL) - ret = arenas_extend(next_arena); - next_arena = (next_arena + 1) % narenas; + assert(arenas[0] != NULL); + for (i = 1; i < narenas_auto; i++) { + if (arenas[i] != NULL) { + /* + * Choose the first arena that has the lowest + * number of threads assigned to it. + */ + if (arenas[i]->nthreads < + arenas[choose]->nthreads) + choose = i; + } else if (first_null == narenas_auto) { + /* + * Record the index of the first uninitialized + * arena, in case all extant arenas are in use. + * + * NB: It is possible for there to be + * discontinuities in terms of initialized + * versus uninitialized arenas, due to the + * "thread.arena" mallctl. + */ + first_null = i; + } + } + + if (arenas[choose]->nthreads == 0 + || first_null == narenas_auto) { + /* + * Use an unloaded arena, or the least loaded arena if + * all arenas are already initialized. + */ + ret = arenas[choose]; + } else { + /* Initialize a new arena. */ + ret = arenas_extend(first_null); + } + ret->nthreads++; malloc_mutex_unlock(&arenas_lock); - } else + } else { ret = arenas[0]; + malloc_mutex_lock(&arenas_lock); + ret->nthreads++; + malloc_mutex_unlock(&arenas_lock); + } - ARENA_SET(ret); + arenas_tsd_set(&ret); return (ret); } -/* - * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so - * provide a wrapper. - */ -int -buferror(int errnum, char *buf, size_t buflen) -{ -#ifdef _GNU_SOURCE - char *b = strerror_r(errno, buf, buflen); - if (b != buf) { - strncpy(buf, b, buflen); - buf[buflen-1] = '\0'; - } - return (0); -#else - return (strerror_r(errno, buf, buflen)); -#endif -} - static void stats_print_atexit(void) { -#if (defined(JEMALLOC_TCACHE) && defined(JEMALLOC_STATS)) - unsigned i; + if (config_tcache && config_stats) { + unsigned narenas, i; - /* - * Merge stats from extant threads. This is racy, since individual - * threads do not lock when recording tcache stats events. As a - * consequence, the final stats may be slightly out of date by the time - * they are reported, if other threads continue to allocate. - */ - for (i = 0; i < narenas; i++) { - arena_t *arena = arenas[i]; - if (arena != NULL) { - tcache_t *tcache; + /* + * Merge stats from extant threads. This is racy, since + * individual threads do not lock when recording tcache stats + * events. As a consequence, the final stats may be slightly + * out of date by the time they are reported, if other threads + * continue to allocate. + */ + for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { + arena_t *arena = arenas[i]; + if (arena != NULL) { + tcache_t *tcache; - /* - * tcache_stats_merge() locks bins, so if any code is - * introduced that acquires both arena and bin locks in - * the opposite order, deadlocks may result. - */ - malloc_mutex_lock(&arena->lock); - ql_foreach(tcache, &arena->tcache_ql, link) { - tcache_stats_merge(tcache, arena); + /* + * tcache_stats_merge() locks bins, so if any + * code is introduced that acquires both arena + * and bin locks in the opposite order, + * deadlocks may result. + */ + malloc_mutex_lock(&arena->lock); + ql_foreach(tcache, &arena->tcache_ql, link) { + tcache_stats_merge(tcache, arena); + } + malloc_mutex_unlock(&arena->lock); } - malloc_mutex_unlock(&arena->lock); } } -#endif - JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL); + je_malloc_stats_print(NULL, NULL, NULL); } /* @@ -227,38 +255,57 @@ malloc_ncpus(void) unsigned ret; long result; +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + result = si.dwNumberOfProcessors; +#else result = sysconf(_SC_NPROCESSORS_ONLN); +#endif if (result == -1) { /* Error. */ ret = 1; - } - ret = (unsigned)result; + } else { + ret = (unsigned)result; + } return (ret); } -#if (defined(JEMALLOC_STATS) && defined(NO_TLS)) -static void -thread_allocated_cleanup(void *arg) +void +arenas_cleanup(void *arg) { - uint64_t *allocated = (uint64_t *)arg; + arena_t *arena = *(arena_t **)arg; - if (allocated != NULL) - idalloc(allocated); + malloc_mutex_lock(&arenas_lock); + arena->nthreads--; + malloc_mutex_unlock(&arenas_lock); } -#endif -/* - * FreeBSD's pthreads implementation calls malloc(3), so the malloc - * implementation has to take pains to avoid infinite recursion during - * initialization. - */ -static inline bool +static JEMALLOC_ATTR(always_inline) void +malloc_thread_init(void) +{ + + /* + * TSD initialization can't be safely done as a side effect of + * deallocation, because it is possible for a thread to do nothing but + * deallocate its TLS data via free(), in which case writing to TLS + * would cause write-after-free memory corruption. The quarantine + * facility *only* gets used as a side effect of deallocation, so make + * a best effort attempt at initializing its TSD by hooking all + * allocation events. + */ + if (config_fill && opt_quarantine) + quarantine_alloc_hook(); +} + +static JEMALLOC_ATTR(always_inline) bool malloc_init(void) { - if (malloc_initialized == false) - return (malloc_init_hard()); + if (malloc_initialized == false && malloc_init_hard()) + return (true); + malloc_thread_init(); return (false); } @@ -274,68 +321,64 @@ malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, for (accept = false; accept == false;) { switch (*opts) { - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case '_': - opts++; - break; - case ':': - opts++; - *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p; - *v_p = opts; - accept = true; - break; - case '\0': - if (opts != *opts_p) { - malloc_write("<jemalloc>: Conf string " - "ends with key\n"); - } - return (true); - default: - malloc_write("<jemalloc>: Malformed conf " - "string\n"); - return (true); + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case '_': + opts++; + break; + case ':': + opts++; + *klen_p = (uintptr_t)opts - 1 - (uintptr_t)*k_p; + *v_p = opts; + accept = true; + break; + case '\0': + if (opts != *opts_p) { + malloc_write("<jemalloc>: Conf string ends " + "with key\n"); + } + return (true); + default: + malloc_write("<jemalloc>: Malformed conf string\n"); + return (true); } } for (accept = false; accept == false;) { switch (*opts) { - case ',': - opts++; - /* - * Look ahead one character here, because the - * next time this function is called, it will - * assume that end of input has been cleanly - * reached if no input remains, but we have - * optimistically already consumed the comma if - * one exists. - */ - if (*opts == '\0') { - malloc_write("<jemalloc>: Conf string " - "ends with comma\n"); - } - *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p; - accept = true; - break; - case '\0': - *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p; - accept = true; - break; - default: - opts++; - break; + case ',': + opts++; + /* + * Look ahead one character here, because the next time + * this function is called, it will assume that end of + * input has been cleanly reached if no input remains, + * but we have optimistically already consumed the + * comma if one exists. + */ + if (*opts == '\0') { + malloc_write("<jemalloc>: Conf string ends " + "with comma\n"); + } + *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p; + accept = true; + break; + case '\0': + *vlen_p = (uintptr_t)opts - (uintptr_t)*v_p; + accept = true; + break; + default: + opts++; + break; } } @@ -347,17 +390,9 @@ static void malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, size_t vlen) { - char buf[PATH_MAX + 1]; - malloc_write("<jemalloc>: "); - malloc_write(msg); - malloc_write(": "); - memcpy(buf, k, klen); - memcpy(&buf[klen], ":", 1); - memcpy(&buf[klen+1], v, vlen); - buf[klen+1+vlen] = '\0'; - malloc_write(buf); - malloc_write("\n"); + malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k, + (int)vlen, v); } static void @@ -368,16 +403,32 @@ malloc_conf_init(void) const char *opts, *k, *v; size_t klen, vlen; + /* + * Automatically configure valgrind before processing options. The + * valgrind option remains in jemalloc 3.x for compatibility reasons. + */ + if (config_valgrind) { + opt_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false; + if (config_fill && opt_valgrind) { + opt_junk = false; + assert(opt_zero == false); + opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT; + opt_redzone = true; + } + if (config_tcache && opt_valgrind) + opt_tcache = false; + } + for (i = 0; i < 3; i++) { /* Get runtime configuration. */ switch (i) { case 0: - if (JEMALLOC_P(malloc_conf) != NULL) { + if (je_malloc_conf != NULL) { /* * Use options that were compiled into the * program. */ - opts = JEMALLOC_P(malloc_conf); + opts = je_malloc_conf; } else { /* No configuration specified. */ buf[0] = '\0'; @@ -385,13 +436,14 @@ malloc_conf_init(void) } break; case 1: { +#ifndef _WIN32 int linklen; const char *linkname = -#ifdef JEMALLOC_PREFIX +# ifdef JEMALLOC_PREFIX "/etc/"JEMALLOC_PREFIX"malloc.conf" -#else +# else "/etc/malloc.conf" -#endif +# endif ; if ((linklen = readlink(linkname, buf, @@ -402,14 +454,15 @@ malloc_conf_init(void) */ buf[linklen] = '\0'; opts = buf; - } else { + } else +#endif + { /* No configuration specified. */ buf[0] = '\0'; opts = buf; } break; - } - case 2: { + } case 2: { const char *envname = #ifdef JEMALLOC_PREFIX JEMALLOC_CPREFIX"MALLOC_CONF" @@ -421,8 +474,8 @@ malloc_conf_init(void) if ((opts = getenv(envname)) != NULL) { /* * Do nothing; opts is already initialized to - * the value of the JEMALLOC_OPTIONS - * environment variable. + * the value of the MALLOC_CONF environment + * variable. */ } else { /* No configuration specified. */ @@ -430,8 +483,7 @@ malloc_conf_init(void) opts = buf; } break; - } - default: + } default: /* NOTREACHED */ assert(false); buf[0] = '\0'; @@ -440,15 +492,15 @@ malloc_conf_init(void) while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v, &vlen) == false) { -#define CONF_HANDLE_BOOL(n) \ - if (sizeof(#n)-1 == klen && strncmp(#n, k, \ +#define CONF_HANDLE_BOOL(o, n) \ + if (sizeof(n)-1 == klen && strncmp(n, k, \ klen) == 0) { \ if (strncmp("true", v, vlen) == 0 && \ vlen == sizeof("true")-1) \ - opt_##n = true; \ + o = true; \ else if (strncmp("false", v, vlen) == \ 0 && vlen == sizeof("false")-1) \ - opt_##n = false; \ + o = false; \ else { \ malloc_conf_error( \ "Invalid conf value", \ @@ -456,36 +508,46 @@ malloc_conf_init(void) } \ continue; \ } -#define CONF_HANDLE_SIZE_T(n, min, max) \ - if (sizeof(#n)-1 == klen && strncmp(#n, k, \ +#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \ + if (sizeof(n)-1 == klen && strncmp(n, k, \ klen) == 0) { \ - unsigned long ul; \ + uintmax_t um; \ char *end; \ \ - errno = 0; \ - ul = strtoul(v, &end, 0); \ - if (errno != 0 || (uintptr_t)end - \ + set_errno(0); \ + um = malloc_strtoumax(v, &end, 0); \ + if (get_errno() != 0 || (uintptr_t)end -\ (uintptr_t)v != vlen) { \ malloc_conf_error( \ "Invalid conf value", \ k, klen, v, vlen); \ - } else if (ul < min || ul > max) { \ - malloc_conf_error( \ - "Out-of-range conf value", \ - k, klen, v, vlen); \ - } else \ - opt_##n = ul; \ + } else if (clip) { \ + if (um < min) \ + o = min; \ + else if (um > max) \ + o = max; \ + else \ + o = um; \ + } else { \ + if (um < min || um > max) { \ + malloc_conf_error( \ + "Out-of-range " \ + "conf value", \ + k, klen, v, vlen); \ + } else \ + o = um; \ + } \ continue; \ } -#define CONF_HANDLE_SSIZE_T(n, min, max) \ - if (sizeof(#n)-1 == klen && strncmp(#n, k, \ +#define CONF_HANDLE_SSIZE_T(o, n, min, max) \ + if (sizeof(n)-1 == klen && strncmp(n, k, \ klen) == 0) { \ long l; \ char *end; \ \ - errno = 0; \ + set_errno(0); \ l = strtol(v, &end, 0); \ - if (errno != 0 || (uintptr_t)end - \ + if (get_errno() != 0 || (uintptr_t)end -\ (uintptr_t)v != vlen) { \ malloc_conf_error( \ "Invalid conf value", \ @@ -496,70 +558,98 @@ malloc_conf_init(void) "Out-of-range conf value", \ k, klen, v, vlen); \ } else \ - opt_##n = l; \ + o = l; \ continue; \ } -#define CONF_HANDLE_CHAR_P(n, d) \ - if (sizeof(#n)-1 == klen && strncmp(#n, k, \ +#define CONF_HANDLE_CHAR_P(o, n, d) \ + if (sizeof(n)-1 == klen && strncmp(n, k, \ klen) == 0) { \ size_t cpylen = (vlen <= \ - sizeof(opt_##n)-1) ? vlen : \ - sizeof(opt_##n)-1; \ - strncpy(opt_##n, v, cpylen); \ - opt_##n[cpylen] = '\0'; \ + sizeof(o)-1) ? vlen : \ + sizeof(o)-1; \ + strncpy(o, v, cpylen); \ + o[cpylen] = '\0'; \ continue; \ } - CONF_HANDLE_BOOL(abort) - CONF_HANDLE_SIZE_T(lg_qspace_max, LG_QUANTUM, - PAGE_SHIFT-1) - CONF_HANDLE_SIZE_T(lg_cspace_max, LG_QUANTUM, - PAGE_SHIFT-1) + CONF_HANDLE_BOOL(opt_abort, "abort") /* - * Chunks always require at least one * header page, - * plus one data page. + * Chunks always require at least one header page, plus + * one data page in the absence of redzones, or three + * pages in the presence of redzones. In order to + * simplify options processing, fix the limit based on + * config_fill. */ - CONF_HANDLE_SIZE_T(lg_chunk, PAGE_SHIFT+1, - (sizeof(size_t) << 3) - 1) - CONF_HANDLE_SIZE_T(narenas, 1, SIZE_T_MAX) - CONF_HANDLE_SSIZE_T(lg_dirty_mult, -1, - (sizeof(size_t) << 3) - 1) - CONF_HANDLE_BOOL(stats_print) -#ifdef JEMALLOC_FILL - CONF_HANDLE_BOOL(junk) - CONF_HANDLE_BOOL(zero) -#endif -#ifdef JEMALLOC_SYSV - CONF_HANDLE_BOOL(sysv) -#endif -#ifdef JEMALLOC_XMALLOC - CONF_HANDLE_BOOL(xmalloc) -#endif -#ifdef JEMALLOC_TCACHE - CONF_HANDLE_BOOL(tcache) - CONF_HANDLE_SSIZE_T(lg_tcache_gc_sweep, -1, - (sizeof(size_t) << 3) - 1) - CONF_HANDLE_SSIZE_T(lg_tcache_max, -1, - (sizeof(size_t) << 3) - 1) -#endif -#ifdef JEMALLOC_PROF - CONF_HANDLE_BOOL(prof) - CONF_HANDLE_CHAR_P(prof_prefix, "jeprof") - CONF_HANDLE_SIZE_T(lg_prof_bt_max, 0, LG_PROF_BT_MAX) - CONF_HANDLE_BOOL(prof_active) - CONF_HANDLE_SSIZE_T(lg_prof_sample, 0, - (sizeof(uint64_t) << 3) - 1) - CONF_HANDLE_BOOL(prof_accum) - CONF_HANDLE_SSIZE_T(lg_prof_tcmax, -1, - (sizeof(size_t) << 3) - 1) - CONF_HANDLE_SSIZE_T(lg_prof_interval, -1, - (sizeof(uint64_t) << 3) - 1) - CONF_HANDLE_BOOL(prof_gdump) - CONF_HANDLE_BOOL(prof_leak) -#endif -#ifdef JEMALLOC_SWAP - CONF_HANDLE_BOOL(overcommit) -#endif + CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE + + (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1, + true) + if (strncmp("dss", k, klen) == 0) { + int i; + bool match = false; + for (i = 0; i < dss_prec_limit; i++) { + if (strncmp(dss_prec_names[i], v, vlen) + == 0) { + if (chunk_dss_prec_set(i)) { + malloc_conf_error( + "Error setting dss", + k, klen, v, vlen); + } else { + opt_dss = + dss_prec_names[i]; + match = true; + break; + } + } + } + if (match == false) { + malloc_conf_error("Invalid conf value", + k, klen, v, vlen); + } + continue; + } + CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1, + SIZE_T_MAX, false) + CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult", + -1, (sizeof(size_t) << 3) - 1) + CONF_HANDLE_BOOL(opt_stats_print, "stats_print") + if (config_fill) { + CONF_HANDLE_BOOL(opt_junk, "junk") + CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine", + 0, SIZE_T_MAX, false) + CONF_HANDLE_BOOL(opt_redzone, "redzone") + CONF_HANDLE_BOOL(opt_zero, "zero") + } + if (config_utrace) { + CONF_HANDLE_BOOL(opt_utrace, "utrace") + } + if (config_valgrind) { + CONF_HANDLE_BOOL(opt_valgrind, "valgrind") + } + if (config_xmalloc) { + CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc") + } + if (config_tcache) { + CONF_HANDLE_BOOL(opt_tcache, "tcache") + CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, + "lg_tcache_max", -1, + (sizeof(size_t) << 3) - 1) + } + if (config_prof) { + CONF_HANDLE_BOOL(opt_prof, "prof") + CONF_HANDLE_CHAR_P(opt_prof_prefix, + "prof_prefix", "jeprof") + CONF_HANDLE_BOOL(opt_prof_active, "prof_active") + CONF_HANDLE_SSIZE_T(opt_lg_prof_sample, + "lg_prof_sample", 0, + (sizeof(uint64_t) << 3) - 1) + CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum") + CONF_HANDLE_SSIZE_T(opt_lg_prof_interval, + "lg_prof_interval", -1, + (sizeof(uint64_t) << 3) - 1) + CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump") + CONF_HANDLE_BOOL(opt_prof_final, "prof_final") + CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak") + } malloc_conf_error("Invalid conf pair", k, klen, v, vlen); #undef CONF_HANDLE_BOOL @@ -567,14 +657,6 @@ malloc_conf_init(void) #undef CONF_HANDLE_SSIZE_T #undef CONF_HANDLE_CHAR_P } - - /* Validate configuration of options that are inter-related. */ - if (opt_lg_qspace_max+1 >= opt_lg_cspace_max) { - malloc_write("<jemalloc>: Invalid lg_[qc]space_max " - "relationship; restoring defaults\n"); - opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT; - opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT; - } } } @@ -584,7 +666,7 @@ malloc_init_hard(void) arena_t *init_arenas[1]; malloc_mutex_lock(&init_lock); - if (malloc_initialized || malloc_initializer == pthread_self()) { + if (malloc_initialized || IS_INITIALIZER) { /* * Another thread initialized the allocator before this one * acquired init_lock, or this thread is the initializing @@ -593,7 +675,8 @@ malloc_init_hard(void) malloc_mutex_unlock(&init_lock); return (false); } - if (malloc_initializer != (unsigned long)0) { +#ifdef JEMALLOC_THREADED_INIT + if (malloc_initializer != NO_INITIALIZER && IS_INITIALIZER == false) { /* Busy-wait until the initializing thread completes. */ do { malloc_mutex_unlock(&init_lock); @@ -603,44 +686,25 @@ malloc_init_hard(void) malloc_mutex_unlock(&init_lock); return (false); } - -#ifdef DYNAMIC_PAGE_SHIFT - /* Get page size. */ - { - long result; - - result = sysconf(_SC_PAGESIZE); - assert(result != -1); - pagesize = (unsigned)result; - - /* - * We assume that pagesize is a power of 2 when calculating - * pagesize_mask and lg_pagesize. - */ - assert(((result - 1) & result) == 0); - pagesize_mask = result - 1; - lg_pagesize = ffs((int)result) - 1; - } #endif + malloc_initializer = INITIALIZER; -#ifdef JEMALLOC_PROF - prof_boot0(); -#endif + malloc_tsd_boot(); + if (config_prof) + prof_boot0(); malloc_conf_init(); +#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \ + && !defined(_WIN32)) /* Register fork handlers. */ - if (pthread_atfork(jemalloc_prefork, jemalloc_postfork, - jemalloc_postfork) != 0) { + if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, + jemalloc_postfork_child) != 0) { malloc_write("<jemalloc>: Error in pthread_atfork()\n"); if (opt_abort) abort(); } - - if (ctl_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } +#endif if (opt_stats_print) { /* Print statistics at exit. */ @@ -651,50 +715,46 @@ malloc_init_hard(void) } } - if (chunk_boot()) { + if (base_boot()) { malloc_mutex_unlock(&init_lock); return (true); } - if (base_boot()) { + if (chunk_boot()) { malloc_mutex_unlock(&init_lock); return (true); } -#ifdef JEMALLOC_PROF - prof_boot1(); -#endif - - if (arena_boot()) { + if (ctl_boot()) { malloc_mutex_unlock(&init_lock); return (true); } -#ifdef JEMALLOC_TCACHE - tcache_boot(); -#endif + if (config_prof) + prof_boot1(); - if (huge_boot()) { + arena_boot(); + + if (config_tcache && tcache_boot0()) { malloc_mutex_unlock(&init_lock); return (true); } -#if (defined(JEMALLOC_STATS) && defined(NO_TLS)) - /* Initialize allocation counters before any allocations can occur. */ - if (pthread_key_create(&thread_allocated_tsd, thread_allocated_cleanup) - != 0) { + if (huge_boot()) { malloc_mutex_unlock(&init_lock); return (true); } -#endif + + if (malloc_mutex_init(&arenas_lock)) + return (true); /* * Create enough scaffolding to allow recursive allocation in * malloc_ncpus(). */ - narenas = 1; + narenas_total = narenas_auto = 1; arenas = init_arenas; - memset(arenas, 0, sizeof(arena_t *) * narenas); + memset(arenas, 0, sizeof(arena_t *) * narenas_auto); /* * Initialize one arena here. The rest are lazily created in @@ -706,28 +766,42 @@ malloc_init_hard(void) return (true); } - /* - * Assign the initial arena to the initial thread, in order to avoid - * spurious creation of an extra arena if the application switches to - * threaded mode. - */ - ARENA_SET(arenas[0]); + /* Initialize allocation counters before any allocations can occur. */ + if (config_stats && thread_allocated_tsd_boot()) { + malloc_mutex_unlock(&init_lock); + return (true); + } - malloc_mutex_init(&arenas_lock); + if (arenas_tsd_boot()) { + malloc_mutex_unlock(&init_lock); + return (true); + } -#ifdef JEMALLOC_PROF - if (prof_boot2()) { + if (config_tcache && tcache_boot1()) { + malloc_mutex_unlock(&init_lock); + return (true); + } + + if (config_fill && quarantine_boot()) { + malloc_mutex_unlock(&init_lock); + return (true); + } + + if (config_prof && prof_boot2()) { malloc_mutex_unlock(&init_lock); return (true); } -#endif /* Get number of CPUs. */ - malloc_initializer = pthread_self(); malloc_mutex_unlock(&init_lock); ncpus = malloc_ncpus(); malloc_mutex_lock(&init_lock); + if (mutex_boot()) { + malloc_mutex_unlock(&init_lock); + return (true); + } + if (opt_narenas == 0) { /* * For SMP systems, create more than one arena per CPU by @@ -738,32 +812,21 @@ malloc_init_hard(void) else opt_narenas = 1; } - narenas = opt_narenas; + narenas_auto = opt_narenas; /* * Make sure that the arenas array can be allocated. In practice, this * limit is enough to allow the allocator to function, but the ctl * machinery will fail to allocate memory at far lower limits. */ - if (narenas > chunksize / sizeof(arena_t *)) { - char buf[UMAX2S_BUFSIZE]; - - narenas = chunksize / sizeof(arena_t *); - malloc_write("<jemalloc>: Reducing narenas to limit ("); - malloc_write(u2s(narenas, 10, buf)); - malloc_write(")\n"); - } - - next_arena = (narenas > 0) ? 1 : 0; - -#ifdef NO_TLS - if (pthread_key_create(&arenas_tsd, NULL) != 0) { - malloc_mutex_unlock(&init_lock); - return (true); + if (narenas_auto > chunksize / sizeof(arena_t *)) { + narenas_auto = chunksize / sizeof(arena_t *); + malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n", + narenas_auto); } -#endif + narenas_total = narenas_auto; /* Allocate and initialize arenas. */ - arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas); + arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total); if (arenas == NULL) { malloc_mutex_unlock(&init_lock); return (true); @@ -772,39 +835,15 @@ malloc_init_hard(void) * Zero the array. In practice, this should always be pre-zeroed, * since it was just mmap()ed, but let's be sure. */ - memset(arenas, 0, sizeof(arena_t *) * narenas); + memset(arenas, 0, sizeof(arena_t *) * narenas_total); /* Copy the pointer to the one arena that was already initialized. */ arenas[0] = init_arenas[0]; -#ifdef JEMALLOC_ZONE - /* Register the custom zone. */ - malloc_zone_register(create_zone()); - - /* - * Convert the default szone to an "overlay zone" that is capable of - * deallocating szone-allocated objects, but allocating new objects - * from jemalloc. - */ - szone2ozone(malloc_default_zone()); -#endif - malloc_initialized = true; malloc_mutex_unlock(&init_lock); return (false); } - -#ifdef JEMALLOC_ZONE -JEMALLOC_ATTR(constructor) -void -jemalloc_darwin_init(void) -{ - - if (malloc_init_hard()) - abort(); -} -#endif - /* * End initialization functions. */ @@ -813,265 +852,201 @@ jemalloc_darwin_init(void) * Begin malloc(3)-compatible functions. */ -JEMALLOC_ATTR(malloc) -JEMALLOC_ATTR(visibility("default")) void * -JEMALLOC_P(malloc)(size_t size) +je_malloc(size_t size) { void *ret; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - size_t usize -# ifdef JEMALLOC_CC_SILENCE - = 0 -# endif - ; -#endif -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt -# ifdef JEMALLOC_CC_SILENCE - = NULL -# endif - ; -#endif + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL); if (malloc_init()) { ret = NULL; - goto OOM; + goto label_oom; } - if (size == 0) { -#ifdef JEMALLOC_SYSV - if (opt_sysv == false) -#endif - size = 1; -#ifdef JEMALLOC_SYSV - else { -# ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { - malloc_write("<jemalloc>: Error in malloc(): " - "invalid size 0\n"); - abort(); - } -# endif - ret = NULL; - goto RETURN; - } -#endif - } + if (size == 0) + size = 1; -#ifdef JEMALLOC_PROF - if (opt_prof) { + if (config_prof && opt_prof) { usize = s2u(size); - if ((cnt = prof_alloc_prep(usize)) == NULL) { + PROF_ALLOC_PREP(1, usize, cnt); + if (cnt == NULL) { ret = NULL; - goto OOM; + goto label_oom; } if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <= - small_maxclass) { - ret = imalloc(small_maxclass+1); + SMALL_MAXCLASS) { + ret = imalloc(SMALL_MAXCLASS+1); if (ret != NULL) arena_prof_promoted(ret, usize); } else ret = imalloc(size); - } else -#endif - { -#ifdef JEMALLOC_STATS - usize = s2u(size); -#endif + } else { + if (config_stats || (config_valgrind && opt_valgrind)) + usize = s2u(size); ret = imalloc(size); } -OOM: +label_oom: if (ret == NULL) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in malloc(): " "out of memory\n"); abort(); } -#endif - errno = ENOMEM; + set_errno(ENOMEM); } - -#ifdef JEMALLOC_SYSV -RETURN: -#endif -#ifdef JEMALLOC_PROF - if (opt_prof && ret != NULL) + if (config_prof && opt_prof && ret != NULL) prof_malloc(ret, usize, cnt); -#endif -#ifdef JEMALLOC_STATS - if (ret != NULL) { - assert(usize == isalloc(ret)); - ALLOCATED_ADD(usize, 0); + if (config_stats && ret != NULL) { + assert(usize == isalloc(ret, config_prof)); + thread_allocated_tsd_get()->allocated += usize; } -#endif + UTRACE(0, size, ret); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false); return (ret); } JEMALLOC_ATTR(nonnull(1)) -JEMALLOC_ATTR(visibility("default")) -int -JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size) +#ifdef JEMALLOC_PROF +/* + * Avoid any uncertainty as to how many backtrace frames to ignore in + * PROF_ALLOC_PREP(). + */ +JEMALLOC_NOINLINE +#endif +static int +imemalign(void **memptr, size_t alignment, size_t size, + size_t min_alignment) { int ret; + size_t usize; void *result; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - size_t usize -# ifdef JEMALLOC_CC_SILENCE - = 0 -# endif - ; -#endif -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt -# ifdef JEMALLOC_CC_SILENCE - = NULL -# endif - ; -#endif + prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL); + + assert(min_alignment != 0); if (malloc_init()) result = NULL; else { - if (size == 0) { -#ifdef JEMALLOC_SYSV - if (opt_sysv == false) -#endif - size = 1; -#ifdef JEMALLOC_SYSV - else { -# ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { - malloc_write("<jemalloc>: Error in " - "posix_memalign(): invalid size " - "0\n"); - abort(); - } -# endif - result = NULL; - *memptr = NULL; - ret = 0; - goto RETURN; - } -#endif - } + if (size == 0) + size = 1; /* Make sure that alignment is a large enough power of 2. */ if (((alignment - 1) & alignment) != 0 - || alignment < sizeof(void *)) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { - malloc_write("<jemalloc>: Error in " - "posix_memalign(): invalid alignment\n"); + || (alignment < min_alignment)) { + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error allocating " + "aligned memory: invalid alignment\n"); abort(); } -#endif result = NULL; ret = EINVAL; - goto RETURN; + goto label_return; } -#ifdef JEMALLOC_PROF - if (opt_prof) { - usize = sa2u(size, alignment, NULL); - if ((cnt = prof_alloc_prep(usize)) == NULL) { + usize = sa2u(size, alignment); + if (usize == 0) { + result = NULL; + ret = ENOMEM; + goto label_return; + } + + if (config_prof && opt_prof) { + PROF_ALLOC_PREP(2, usize, cnt); + if (cnt == NULL) { result = NULL; ret = EINVAL; } else { if (prof_promote && (uintptr_t)cnt != - (uintptr_t)1U && usize <= small_maxclass) { - result = ipalloc(small_maxclass+1, - alignment, false); + (uintptr_t)1U && usize <= SMALL_MAXCLASS) { + assert(sa2u(SMALL_MAXCLASS+1, + alignment) != 0); + result = ipalloc(sa2u(SMALL_MAXCLASS+1, + alignment), alignment, false); if (result != NULL) { arena_prof_promoted(result, usize); } } else { - result = ipalloc(size, alignment, + result = ipalloc(usize, alignment, false); } } } else -#endif - { -#ifdef JEMALLOC_STATS - usize = sa2u(size, alignment, NULL); -#endif - result = ipalloc(size, alignment, false); - } + result = ipalloc(usize, alignment, false); } if (result == NULL) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { - malloc_write("<jemalloc>: Error in posix_memalign(): " - "out of memory\n"); + if (config_xmalloc && opt_xmalloc) { + malloc_write("<jemalloc>: Error allocating aligned " + "memory: out of memory\n"); abort(); } -#endif ret = ENOMEM; - goto RETURN; + goto label_return; } *memptr = result; ret = 0; -RETURN: -#ifdef JEMALLOC_STATS - if (result != NULL) { - assert(usize == isalloc(result)); - ALLOCATED_ADD(usize, 0); +label_return: + if (config_stats && result != NULL) { + assert(usize == isalloc(result, config_prof)); + thread_allocated_tsd_get()->allocated += usize; } -#endif -#ifdef JEMALLOC_PROF - if (opt_prof && result != NULL) + if (config_prof && opt_prof && result != NULL) prof_malloc(result, usize, cnt); -#endif + UTRACE(0, size, result); + return (ret); +} + +int +je_posix_memalign(void **memptr, size_t alignment, size_t size) +{ + int ret = imemalign(memptr, alignment, size, sizeof(void *)); + JEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr, + config_prof), false); + return (ret); +} + +void * +je_aligned_alloc(size_t alignment, size_t size) +{ + void *ret; + int err; + + if ((err = imemalign(&ret, alignment, size, 1)) != 0) { + ret = NULL; + set_errno(err); + } + JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof), + false); return (ret); } -JEMALLOC_ATTR(malloc) -JEMALLOC_ATTR(visibility("default")) void * -JEMALLOC_P(calloc)(size_t num, size_t size) +je_calloc(size_t num, size_t size) { void *ret; size_t num_size; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - size_t usize -# ifdef JEMALLOC_CC_SILENCE - = 0 -# endif - ; -#endif -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt -# ifdef JEMALLOC_CC_SILENCE - = NULL -# endif - ; -#endif + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL); if (malloc_init()) { num_size = 0; ret = NULL; - goto RETURN; + goto label_return; } num_size = num * size; if (num_size == 0) { -#ifdef JEMALLOC_SYSV - if ((opt_sysv == false) && ((num == 0) || (size == 0))) -#endif + if (num == 0 || size == 0) num_size = 1; -#ifdef JEMALLOC_SYSV else { ret = NULL; - goto RETURN; + goto label_return; } -#endif /* * Try to avoid division here. We know that it isn't possible to * overflow during multiplication if neither operand uses any of the @@ -1081,181 +1056,159 @@ JEMALLOC_P(calloc)(size_t num, size_t size) && (num_size / size != num)) { /* size_t overflow. */ ret = NULL; - goto RETURN; + goto label_return; } -#ifdef JEMALLOC_PROF - if (opt_prof) { + if (config_prof && opt_prof) { usize = s2u(num_size); - if ((cnt = prof_alloc_prep(usize)) == NULL) { + PROF_ALLOC_PREP(1, usize, cnt); + if (cnt == NULL) { ret = NULL; - goto RETURN; + goto label_return; } if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize - <= small_maxclass) { - ret = icalloc(small_maxclass+1); + <= SMALL_MAXCLASS) { + ret = icalloc(SMALL_MAXCLASS+1); if (ret != NULL) arena_prof_promoted(ret, usize); } else ret = icalloc(num_size); - } else -#endif - { -#ifdef JEMALLOC_STATS - usize = s2u(num_size); -#endif + } else { + if (config_stats || (config_valgrind && opt_valgrind)) + usize = s2u(num_size); ret = icalloc(num_size); } -RETURN: +label_return: if (ret == NULL) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in calloc(): out of " "memory\n"); abort(); } -#endif - errno = ENOMEM; + set_errno(ENOMEM); } -#ifdef JEMALLOC_PROF - if (opt_prof && ret != NULL) + if (config_prof && opt_prof && ret != NULL) prof_malloc(ret, usize, cnt); -#endif -#ifdef JEMALLOC_STATS - if (ret != NULL) { - assert(usize == isalloc(ret)); - ALLOCATED_ADD(usize, 0); + if (config_stats && ret != NULL) { + assert(usize == isalloc(ret, config_prof)); + thread_allocated_tsd_get()->allocated += usize; } -#endif + UTRACE(0, num_size, ret); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true); return (ret); } -JEMALLOC_ATTR(visibility("default")) void * -JEMALLOC_P(realloc)(void *ptr, size_t size) +je_realloc(void *ptr, size_t size) { void *ret; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - size_t usize -# ifdef JEMALLOC_CC_SILENCE - = 0 -# endif - ; + size_t usize JEMALLOC_CC_SILENCE_INIT(0); size_t old_size = 0; -#endif -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt -# ifdef JEMALLOC_CC_SILENCE - = NULL -# endif - ; - prof_ctx_t *old_ctx -# ifdef JEMALLOC_CC_SILENCE - = NULL -# endif - ; -#endif + size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); + prof_thr_cnt_t *cnt JEMALLOC_CC_SILENCE_INIT(NULL); + prof_ctx_t *old_ctx JEMALLOC_CC_SILENCE_INIT(NULL); if (size == 0) { -#ifdef JEMALLOC_SYSV - if (opt_sysv == false) -#endif - size = 1; -#ifdef JEMALLOC_SYSV - else { - if (ptr != NULL) { -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - old_size = isalloc(ptr); -#endif -#ifdef JEMALLOC_PROF - if (opt_prof) { - old_ctx = prof_ctx_get(ptr); - cnt = NULL; - } -#endif - idalloc(ptr); + if (ptr != NULL) { + /* realloc(ptr, 0) is equivalent to free(p). */ + assert(malloc_initialized || IS_INITIALIZER); + if (config_prof) { + old_size = isalloc(ptr, true); + if (config_valgrind && opt_valgrind) + old_rzsize = p2rz(ptr); + } else if (config_stats) { + old_size = isalloc(ptr, false); + if (config_valgrind && opt_valgrind) + old_rzsize = u2rz(old_size); + } else if (config_valgrind && opt_valgrind) { + old_size = isalloc(ptr, false); + old_rzsize = u2rz(old_size); } -#ifdef JEMALLOC_PROF - else if (opt_prof) { - old_ctx = NULL; + if (config_prof && opt_prof) { + old_ctx = prof_ctx_get(ptr); cnt = NULL; } -#endif + iqalloc(ptr); ret = NULL; - goto RETURN; - } -#endif + goto label_return; + } else + size = 1; } if (ptr != NULL) { - assert(malloc_initialized || malloc_initializer == - pthread_self()); - -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - old_size = isalloc(ptr); -#endif -#ifdef JEMALLOC_PROF - if (opt_prof) { + assert(malloc_initialized || IS_INITIALIZER); + malloc_thread_init(); + + if (config_prof) { + old_size = isalloc(ptr, true); + if (config_valgrind && opt_valgrind) + old_rzsize = p2rz(ptr); + } else if (config_stats) { + old_size = isalloc(ptr, false); + if (config_valgrind && opt_valgrind) + old_rzsize = u2rz(old_size); + } else if (config_valgrind && opt_valgrind) { + old_size = isalloc(ptr, false); + old_rzsize = u2rz(old_size); + } + if (config_prof && opt_prof) { usize = s2u(size); old_ctx = prof_ctx_get(ptr); - if ((cnt = prof_alloc_prep(usize)) == NULL) { + PROF_ALLOC_PREP(1, usize, cnt); + if (cnt == NULL) { + old_ctx = NULL; ret = NULL; - goto OOM; + goto label_oom; } if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && - usize <= small_maxclass) { - ret = iralloc(ptr, small_maxclass+1, 0, 0, + usize <= SMALL_MAXCLASS) { + ret = iralloc(ptr, SMALL_MAXCLASS+1, 0, 0, false, false); if (ret != NULL) arena_prof_promoted(ret, usize); - } else + else + old_ctx = NULL; + } else { ret = iralloc(ptr, size, 0, 0, false, false); - } else -#endif - { -#ifdef JEMALLOC_STATS - usize = s2u(size); -#endif + if (ret == NULL) + old_ctx = NULL; + } + } else { + if (config_stats || (config_valgrind && opt_valgrind)) + usize = s2u(size); ret = iralloc(ptr, size, 0, 0, false, false); } -#ifdef JEMALLOC_PROF -OOM: -#endif +label_oom: if (ret == NULL) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in realloc(): " "out of memory\n"); abort(); } -#endif - errno = ENOMEM; + set_errno(ENOMEM); } } else { -#ifdef JEMALLOC_PROF - if (opt_prof) + /* realloc(NULL, size) is equivalent to malloc(size). */ + if (config_prof && opt_prof) old_ctx = NULL; -#endif if (malloc_init()) { -#ifdef JEMALLOC_PROF - if (opt_prof) + if (config_prof && opt_prof) cnt = NULL; -#endif ret = NULL; } else { -#ifdef JEMALLOC_PROF - if (opt_prof) { + if (config_prof && opt_prof) { usize = s2u(size); - if ((cnt = prof_alloc_prep(usize)) == NULL) + PROF_ALLOC_PREP(1, usize, cnt); + if (cnt == NULL) ret = NULL; else { if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <= - small_maxclass) { - ret = imalloc(small_maxclass+1); + SMALL_MAXCLASS) { + ret = imalloc(SMALL_MAXCLASS+1); if (ret != NULL) { arena_prof_promoted(ret, usize); @@ -1263,72 +1216,61 @@ OOM: } else ret = imalloc(size); } - } else -#endif - { -#ifdef JEMALLOC_STATS - usize = s2u(size); -#endif + } else { + if (config_stats || (config_valgrind && + opt_valgrind)) + usize = s2u(size); ret = imalloc(size); } } if (ret == NULL) { -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in realloc(): " "out of memory\n"); abort(); } -#endif - errno = ENOMEM; + set_errno(ENOMEM); } } -#ifdef JEMALLOC_SYSV -RETURN: -#endif -#ifdef JEMALLOC_PROF - if (opt_prof) +label_return: + if (config_prof && opt_prof) prof_realloc(ret, usize, cnt, old_size, old_ctx); -#endif -#ifdef JEMALLOC_STATS - if (ret != NULL) { - assert(usize == isalloc(ret)); - ALLOCATED_ADD(usize, old_size); + if (config_stats && ret != NULL) { + thread_allocated_t *ta; + assert(usize == isalloc(ret, config_prof)); + ta = thread_allocated_tsd_get(); + ta->allocated += usize; + ta->deallocated += old_size; } -#endif + UTRACE(ptr, size, ret); + JEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_size, old_rzsize, false); return (ret); } -JEMALLOC_ATTR(visibility("default")) void -JEMALLOC_P(free)(void *ptr) +je_free(void *ptr) { + UTRACE(ptr, 0, 0); if (ptr != NULL) { -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) size_t usize; -#endif + size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); - assert(malloc_initialized || malloc_initializer == - pthread_self()); + assert(malloc_initialized || IS_INITIALIZER); -#ifdef JEMALLOC_STATS - usize = isalloc(ptr); -#endif -#ifdef JEMALLOC_PROF - if (opt_prof) { -# ifndef JEMALLOC_STATS - usize = isalloc(ptr); -# endif + if (config_prof && opt_prof) { + usize = isalloc(ptr, config_prof); prof_free(ptr, usize); - } -#endif -#ifdef JEMALLOC_STATS - ALLOCATED_ADD(0, usize); -#endif - idalloc(ptr); + } else if (config_stats || config_valgrind) + usize = isalloc(ptr, config_prof); + if (config_stats) + thread_allocated_tsd_get()->deallocated += usize; + if (config_valgrind && opt_valgrind) + rzsize = p2rz(ptr); + iqalloc(ptr); + JEMALLOC_VALGRIND_FREE(ptr, rzsize); } } @@ -1338,51 +1280,55 @@ JEMALLOC_P(free)(void *ptr) /******************************************************************************/ /* * Begin non-standard override functions. - * - * These overrides are omitted if the JEMALLOC_PREFIX is defined, since the - * entire point is to avoid accidental mixed allocator usage. */ -#ifndef JEMALLOC_PREFIX #ifdef JEMALLOC_OVERRIDE_MEMALIGN -JEMALLOC_ATTR(malloc) -JEMALLOC_ATTR(visibility("default")) void * -JEMALLOC_P(memalign)(size_t alignment, size_t size) +je_memalign(size_t alignment, size_t size) { - void *ret; -#ifdef JEMALLOC_CC_SILENCE - int result = -#endif - JEMALLOC_P(posix_memalign)(&ret, alignment, size); -#ifdef JEMALLOC_CC_SILENCE - if (result != 0) - return (NULL); -#endif + void *ret JEMALLOC_CC_SILENCE_INIT(NULL); + imemalign(&ret, alignment, size, 1); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); return (ret); } #endif #ifdef JEMALLOC_OVERRIDE_VALLOC -JEMALLOC_ATTR(malloc) -JEMALLOC_ATTR(visibility("default")) void * -JEMALLOC_P(valloc)(size_t size) +je_valloc(size_t size) { - void *ret; -#ifdef JEMALLOC_CC_SILENCE - int result = -#endif - JEMALLOC_P(posix_memalign)(&ret, PAGE_SIZE, size); -#ifdef JEMALLOC_CC_SILENCE - if (result != 0) - return (NULL); -#endif + void *ret JEMALLOC_CC_SILENCE_INIT(NULL); + imemalign(&ret, PAGE, size, 1); + JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); return (ret); } #endif -#endif /* JEMALLOC_PREFIX */ +/* + * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has + * #define je_malloc malloc + */ +#define malloc_is_malloc 1 +#define is_malloc_(a) malloc_is_ ## a +#define is_malloc(a) is_malloc_(a) + +#if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__)) +/* + * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible + * to inconsistently reference libc's malloc(3)-compatible functions + * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541). + * + * These definitions interpose hooks in glibc. The functions are actually + * passed an extra argument for the caller return address, which will be + * ignored. + */ +JEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free; +JEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc; +JEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc; +JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) = + je_memalign; +#endif + /* * End non-standard override functions. */ @@ -1391,36 +1337,32 @@ JEMALLOC_P(valloc)(size_t size) * Begin non-standard functions. */ -JEMALLOC_ATTR(visibility("default")) size_t -JEMALLOC_P(malloc_usable_size)(const void *ptr) +je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { size_t ret; - assert(malloc_initialized || malloc_initializer == pthread_self()); + assert(malloc_initialized || IS_INITIALIZER); + malloc_thread_init(); -#ifdef JEMALLOC_IVSALLOC - ret = ivsalloc(ptr); -#else - assert(ptr != NULL); - ret = isalloc(ptr); -#endif + if (config_ivsalloc) + ret = ivsalloc(ptr, config_prof); + else + ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0; return (ret); } -JEMALLOC_ATTR(visibility("default")) void -JEMALLOC_P(malloc_stats_print)(void (*write_cb)(void *, const char *), - void *cbopaque, const char *opts) +je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, + const char *opts) { stats_print(write_cb, cbopaque, opts); } -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(mallctl)(const char *name, void *oldp, size_t *oldlenp, void *newp, +je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { @@ -1430,9 +1372,8 @@ JEMALLOC_P(mallctl)(const char *name, void *oldp, size_t *oldlenp, void *newp, return (ctl_byname(name, oldp, oldlenp, newp, newlen)); } -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp) +je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { if (malloc_init()) @@ -1441,10 +1382,9 @@ JEMALLOC_P(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp) return (ctl_nametomib(name, mibp, miblenp)); } -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) +je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) { if (malloc_init()) @@ -1453,307 +1393,476 @@ JEMALLOC_P(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen)); } -JEMALLOC_INLINE void * -iallocm(size_t size, size_t alignment, bool zero) +/* + * End non-standard functions. + */ +/******************************************************************************/ +/* + * Begin experimental functions. + */ +#ifdef JEMALLOC_EXPERIMENTAL + +static JEMALLOC_ATTR(always_inline) void * +iallocm(size_t usize, size_t alignment, bool zero, bool try_tcache, + arena_t *arena) { + assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize, + alignment))); + if (alignment != 0) - return (ipalloc(size, alignment, zero)); + return (ipallocx(usize, alignment, zero, try_tcache, arena)); else if (zero) - return (icalloc(size)); + return (icallocx(usize, try_tcache, arena)); else - return (imalloc(size)); + return (imallocx(usize, try_tcache, arena)); } -JEMALLOC_ATTR(nonnull(1)) -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags) +je_allocm(void **ptr, size_t *rsize, size_t size, int flags) { void *p; size_t usize; size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK) & (SIZE_T_MAX-1)); bool zero = flags & ALLOCM_ZERO; -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt; -#endif + unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + arena_t *arena; + bool try_tcache; assert(ptr != NULL); assert(size != 0); if (malloc_init()) - goto OOM; + goto label_oom; -#ifdef JEMALLOC_PROF - if (opt_prof) { - usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment, - NULL); - if ((cnt = prof_alloc_prep(usize)) == NULL) - goto OOM; + if (arena_ind != UINT_MAX) { + arena = arenas[arena_ind]; + try_tcache = false; + } else { + arena = NULL; + try_tcache = true; + } + + usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); + if (usize == 0) + goto label_oom; + + if (config_prof && opt_prof) { + prof_thr_cnt_t *cnt; + + PROF_ALLOC_PREP(1, usize, cnt); + if (cnt == NULL) + goto label_oom; if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <= - small_maxclass) { - p = iallocm(small_maxclass+1, alignment, zero); + SMALL_MAXCLASS) { + size_t usize_promoted = (alignment == 0) ? + s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, + alignment); + assert(usize_promoted != 0); + p = iallocm(usize_promoted, alignment, zero, + try_tcache, arena); if (p == NULL) - goto OOM; + goto label_oom; arena_prof_promoted(p, usize); } else { - p = iallocm(size, alignment, zero); + p = iallocm(usize, alignment, zero, try_tcache, arena); if (p == NULL) - goto OOM; + goto label_oom; } - - if (rsize != NULL) - *rsize = usize; - } else -#endif - { - p = iallocm(size, alignment, zero); + prof_malloc(p, usize, cnt); + } else { + p = iallocm(usize, alignment, zero, try_tcache, arena); if (p == NULL) - goto OOM; -#ifndef JEMALLOC_STATS - if (rsize != NULL) -#endif - { - usize = (alignment == 0) ? s2u(size) : sa2u(size, - alignment, NULL); -#ifdef JEMALLOC_STATS - if (rsize != NULL) -#endif - *rsize = usize; - } + goto label_oom; } + if (rsize != NULL) + *rsize = usize; *ptr = p; -#ifdef JEMALLOC_STATS - assert(usize == isalloc(p)); - ALLOCATED_ADD(usize, 0); -#endif + if (config_stats) { + assert(usize == isalloc(p, config_prof)); + thread_allocated_tsd_get()->allocated += usize; + } + UTRACE(0, size, p); + JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero); return (ALLOCM_SUCCESS); -OOM: -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { +label_oom: + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in allocm(): " "out of memory\n"); abort(); } -#endif *ptr = NULL; + UTRACE(0, size, 0); return (ALLOCM_ERR_OOM); } -JEMALLOC_ATTR(nonnull(1)) -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra, - int flags) +je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags) { void *p, *q; size_t usize; -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) size_t old_size; -#endif + size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK) & (SIZE_T_MAX-1)); bool zero = flags & ALLOCM_ZERO; bool no_move = flags & ALLOCM_NO_MOVE; -#ifdef JEMALLOC_PROF - prof_thr_cnt_t *cnt; - prof_ctx_t *old_ctx; -#endif + unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + bool try_tcache_alloc, try_tcache_dalloc; + arena_t *arena; assert(ptr != NULL); assert(*ptr != NULL); assert(size != 0); assert(SIZE_T_MAX - size >= extra); - assert(malloc_initialized || malloc_initializer == pthread_self()); + assert(malloc_initialized || IS_INITIALIZER); + malloc_thread_init(); + + if (arena_ind != UINT_MAX) { + arena_chunk_t *chunk; + try_tcache_alloc = true; + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(*ptr); + try_tcache_dalloc = (chunk == *ptr || chunk->arena != + arenas[arena_ind]); + arena = arenas[arena_ind]; + } else { + try_tcache_alloc = true; + try_tcache_dalloc = true; + arena = NULL; + } p = *ptr; -#ifdef JEMALLOC_PROF - if (opt_prof) { + if (config_prof && opt_prof) { + prof_thr_cnt_t *cnt; + /* * usize isn't knowable before iralloc() returns when extra is * non-zero. Therefore, compute its maximum possible value and - * use that in prof_alloc_prep() to decide whether to capture a + * use that in PROF_ALLOC_PREP() to decide whether to capture a * backtrace. prof_realloc() will use the actual usize to * decide whether to sample. */ size_t max_usize = (alignment == 0) ? s2u(size+extra) : - sa2u(size+extra, alignment, NULL); - old_size = isalloc(p); - old_ctx = prof_ctx_get(p); - if ((cnt = prof_alloc_prep(max_usize)) == NULL) - goto OOM; - if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && max_usize - <= small_maxclass) { - q = iralloc(p, small_maxclass+1, (small_maxclass+1 >= - size+extra) ? 0 : size+extra - (small_maxclass+1), - alignment, zero, no_move); + sa2u(size+extra, alignment); + prof_ctx_t *old_ctx = prof_ctx_get(p); + old_size = isalloc(p, true); + if (config_valgrind && opt_valgrind) + old_rzsize = p2rz(p); + PROF_ALLOC_PREP(1, max_usize, cnt); + if (cnt == NULL) + goto label_oom; + /* + * Use minimum usize to determine whether promotion may happen. + */ + if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U + && ((alignment == 0) ? s2u(size) : sa2u(size, alignment)) + <= SMALL_MAXCLASS) { + q = irallocx(p, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >= + size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1), + alignment, zero, no_move, try_tcache_alloc, + try_tcache_dalloc, arena); if (q == NULL) - goto ERR; - usize = isalloc(q); - arena_prof_promoted(q, usize); + goto label_err; + if (max_usize < PAGE) { + usize = max_usize; + arena_prof_promoted(q, usize); + } else + usize = isalloc(q, config_prof); } else { - q = iralloc(p, size, extra, alignment, zero, no_move); + q = irallocx(p, size, extra, alignment, zero, no_move, + try_tcache_alloc, try_tcache_dalloc, arena); if (q == NULL) - goto ERR; - usize = isalloc(q); + goto label_err; + usize = isalloc(q, config_prof); } prof_realloc(q, usize, cnt, old_size, old_ctx); - } else -#endif - { -#ifdef JEMALLOC_STATS - old_size = isalloc(p); -#endif - q = iralloc(p, size, extra, alignment, zero, no_move); - if (q == NULL) - goto ERR; -#ifndef JEMALLOC_STATS if (rsize != NULL) -#endif - { - usize = isalloc(q); -#ifdef JEMALLOC_STATS - if (rsize != NULL) -#endif - *rsize = usize; + *rsize = usize; + } else { + if (config_stats) { + old_size = isalloc(p, false); + if (config_valgrind && opt_valgrind) + old_rzsize = u2rz(old_size); + } else if (config_valgrind && opt_valgrind) { + old_size = isalloc(p, false); + old_rzsize = u2rz(old_size); + } + q = irallocx(p, size, extra, alignment, zero, no_move, + try_tcache_alloc, try_tcache_dalloc, arena); + if (q == NULL) + goto label_err; + if (config_stats) + usize = isalloc(q, config_prof); + if (rsize != NULL) { + if (config_stats == false) + usize = isalloc(q, config_prof); + *rsize = usize; } } *ptr = q; -#ifdef JEMALLOC_STATS - ALLOCATED_ADD(usize, old_size); -#endif + if (config_stats) { + thread_allocated_t *ta; + ta = thread_allocated_tsd_get(); + ta->allocated += usize; + ta->deallocated += old_size; + } + UTRACE(p, size, q); + JEMALLOC_VALGRIND_REALLOC(q, usize, p, old_size, old_rzsize, zero); return (ALLOCM_SUCCESS); -ERR: - if (no_move) +label_err: + if (no_move) { + UTRACE(p, size, q); return (ALLOCM_ERR_NOT_MOVED); -#ifdef JEMALLOC_PROF -OOM: -#endif -#ifdef JEMALLOC_XMALLOC - if (opt_xmalloc) { + } +label_oom: + if (config_xmalloc && opt_xmalloc) { malloc_write("<jemalloc>: Error in rallocm(): " "out of memory\n"); abort(); } -#endif + UTRACE(p, size, 0); return (ALLOCM_ERR_OOM); } -JEMALLOC_ATTR(nonnull(1)) -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(sallocm)(const void *ptr, size_t *rsize, int flags) +je_sallocm(const void *ptr, size_t *rsize, int flags) { size_t sz; - assert(malloc_initialized || malloc_initializer == pthread_self()); + assert(malloc_initialized || IS_INITIALIZER); + malloc_thread_init(); -#ifdef JEMALLOC_IVSALLOC - sz = ivsalloc(ptr); -#else - assert(ptr != NULL); - sz = isalloc(ptr); -#endif + if (config_ivsalloc) + sz = ivsalloc(ptr, config_prof); + else { + assert(ptr != NULL); + sz = isalloc(ptr, config_prof); + } assert(rsize != NULL); *rsize = sz; return (ALLOCM_SUCCESS); } -JEMALLOC_ATTR(nonnull(1)) -JEMALLOC_ATTR(visibility("default")) int -JEMALLOC_P(dallocm)(void *ptr, int flags) +je_dallocm(void *ptr, int flags) { -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) size_t usize; -#endif + size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); + unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; + bool try_tcache; assert(ptr != NULL); - assert(malloc_initialized || malloc_initializer == pthread_self()); + assert(malloc_initialized || IS_INITIALIZER); -#ifdef JEMALLOC_STATS - usize = isalloc(ptr); -#endif -#ifdef JEMALLOC_PROF - if (opt_prof) { -# ifndef JEMALLOC_STATS - usize = isalloc(ptr); -# endif + if (arena_ind != UINT_MAX) { + arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); + try_tcache = (chunk == ptr || chunk->arena != + arenas[arena_ind]); + } else + try_tcache = true; + + UTRACE(ptr, 0, 0); + if (config_stats || config_valgrind) + usize = isalloc(ptr, config_prof); + if (config_prof && opt_prof) { + if (config_stats == false && config_valgrind == false) + usize = isalloc(ptr, config_prof); prof_free(ptr, usize); } -#endif -#ifdef JEMALLOC_STATS - ALLOCATED_ADD(0, usize); -#endif - idalloc(ptr); + if (config_stats) + thread_allocated_tsd_get()->deallocated += usize; + if (config_valgrind && opt_valgrind) + rzsize = p2rz(ptr); + iqallocx(ptr, try_tcache); + JEMALLOC_VALGRIND_FREE(ptr, rzsize); + + return (ALLOCM_SUCCESS); +} + +int +je_nallocm(size_t *rsize, size_t size, int flags) +{ + size_t usize; + size_t alignment = (ZU(1) << (flags & ALLOCM_LG_ALIGN_MASK) + & (SIZE_T_MAX-1)); + assert(size != 0); + + if (malloc_init()) + return (ALLOCM_ERR_OOM); + + usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); + if (usize == 0) + return (ALLOCM_ERR_OOM); + + if (rsize != NULL) + *rsize = usize; return (ALLOCM_SUCCESS); } +#endif /* - * End non-standard functions. + * End experimental functions. */ /******************************************************************************/ - /* * The following functions are used by threading libraries for protection of * malloc during fork(). */ +/* + * If an application creates a thread before doing any allocation in the main + * thread, then calls fork(2) in the main thread followed by memory allocation + * in the child process, a race can occur that results in deadlock within the + * child: the main thread may have forked while the created thread had + * partially initialized the allocator. Ordinarily jemalloc prevents + * fork/malloc races via the following functions it registers during + * initialization using pthread_atfork(), but of course that does no good if + * the allocator isn't fully initialized at fork time. The following library + * constructor is a partial solution to this problem. It may still possible to + * trigger the deadlock described above, but doing so would involve forking via + * a library constructor that runs before jemalloc's runs. + */ +JEMALLOC_ATTR(constructor) +static void +jemalloc_constructor(void) +{ + + malloc_init(); +} + +#ifndef JEMALLOC_MUTEX_INIT_CB void jemalloc_prefork(void) +#else +JEMALLOC_EXPORT void +_malloc_prefork(void) +#endif { unsigned i; - /* Acquire all mutexes in a safe order. */ +#ifdef JEMALLOC_MUTEX_INIT_CB + if (malloc_initialized == false) + return; +#endif + assert(malloc_initialized); - malloc_mutex_lock(&arenas_lock); - for (i = 0; i < narenas; i++) { + /* Acquire all mutexes in a safe order. */ + ctl_prefork(); + prof_prefork(); + malloc_mutex_prefork(&arenas_lock); + for (i = 0; i < narenas_total; i++) { if (arenas[i] != NULL) - malloc_mutex_lock(&arenas[i]->lock); + arena_prefork(arenas[i]); } + chunk_prefork(); + base_prefork(); + huge_prefork(); +} - malloc_mutex_lock(&base_mtx); - - malloc_mutex_lock(&huge_mtx); - -#ifdef JEMALLOC_DSS - malloc_mutex_lock(&dss_mtx); +#ifndef JEMALLOC_MUTEX_INIT_CB +void +jemalloc_postfork_parent(void) +#else +JEMALLOC_EXPORT void +_malloc_postfork(void) #endif +{ + unsigned i; -#ifdef JEMALLOC_SWAP - malloc_mutex_lock(&swap_mtx); +#ifdef JEMALLOC_MUTEX_INIT_CB + if (malloc_initialized == false) + return; #endif + assert(malloc_initialized); + + /* Release all mutexes, now that fork() has completed. */ + huge_postfork_parent(); + base_postfork_parent(); + chunk_postfork_parent(); + for (i = 0; i < narenas_total; i++) { + if (arenas[i] != NULL) + arena_postfork_parent(arenas[i]); + } + malloc_mutex_postfork_parent(&arenas_lock); + prof_postfork_parent(); + ctl_postfork_parent(); } void -jemalloc_postfork(void) +jemalloc_postfork_child(void) { unsigned i; + assert(malloc_initialized); + /* Release all mutexes, now that fork() has completed. */ + huge_postfork_child(); + base_postfork_child(); + chunk_postfork_child(); + for (i = 0; i < narenas_total; i++) { + if (arenas[i] != NULL) + arena_postfork_child(arenas[i]); + } + malloc_mutex_postfork_child(&arenas_lock); + prof_postfork_child(); + ctl_postfork_child(); +} -#ifdef JEMALLOC_SWAP - malloc_mutex_unlock(&swap_mtx); -#endif +/******************************************************************************/ +/* + * The following functions are used for TLS allocation/deallocation in static + * binaries on FreeBSD. The primary difference between these and i[mcd]alloc() + * is that these avoid accessing TLS variables. + */ -#ifdef JEMALLOC_DSS - malloc_mutex_unlock(&dss_mtx); -#endif +static void * +a0alloc(size_t size, bool zero) +{ - malloc_mutex_unlock(&huge_mtx); + if (malloc_init()) + return (NULL); - malloc_mutex_unlock(&base_mtx); + if (size == 0) + size = 1; - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_mutex_unlock(&arenas[i]->lock); - } - malloc_mutex_unlock(&arenas_lock); + if (size <= arena_maxclass) + return (arena_malloc(arenas[0], size, zero, false)); + else + return (huge_malloc(size, zero)); +} + +void * +a0malloc(size_t size) +{ + + return (a0alloc(size, false)); +} + +void * +a0calloc(size_t num, size_t size) +{ + + return (a0alloc(num * size, true)); +} + +void +a0free(void *ptr) +{ + arena_chunk_t *chunk; + + if (ptr == NULL) + return; + + chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); + if (chunk != ptr) + arena_dalloc(chunk->arena, chunk, ptr, false); + else + huge_dalloc(ptr, true); } /******************************************************************************/ diff --git a/dep/jemalloc/src/mb.c b/dep/jemalloc/src/mb.c index 30a1a2e997a..dc2c0a256fd 100644 --- a/dep/jemalloc/src/mb.c +++ b/dep/jemalloc/src/mb.c @@ -1,2 +1,2 @@ -#define MB_C_ +#define JEMALLOC_MB_C_ #include "jemalloc/internal/jemalloc_internal.h" diff --git a/dep/jemalloc/src/mutex.c b/dep/jemalloc/src/mutex.c index 3ecb18a340e..55e18c23713 100644 --- a/dep/jemalloc/src/mutex.c +++ b/dep/jemalloc/src/mutex.c @@ -1,14 +1,26 @@ #define JEMALLOC_MUTEX_C_ #include "jemalloc/internal/jemalloc_internal.h" +#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) +#include <dlfcn.h> +#endif + +#ifndef _CRT_SPINCOUNT +#define _CRT_SPINCOUNT 4000 +#endif + /******************************************************************************/ /* Data. */ #ifdef JEMALLOC_LAZY_LOCK bool isthreaded = false; #endif +#ifdef JEMALLOC_MUTEX_INIT_CB +static bool postpone_init = true; +static malloc_mutex_t *postponed_mutexes = NULL; +#endif -#ifdef JEMALLOC_LAZY_LOCK +#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) static void pthread_create_once(void); #endif @@ -18,7 +30,7 @@ static void pthread_create_once(void); * process goes multi-threaded. */ -#ifdef JEMALLOC_LAZY_LOCK +#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, void *(*)(void *), void *__restrict); @@ -36,8 +48,7 @@ pthread_create_once(void) isthreaded = true; } -JEMALLOC_ATTR(visibility("default")) -int +JEMALLOC_EXPORT int pthread_create(pthread_t *__restrict thread, const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), void *__restrict arg) @@ -52,33 +63,87 @@ pthread_create(pthread_t *__restrict thread, /******************************************************************************/ +#ifdef JEMALLOC_MUTEX_INIT_CB +JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, + void *(calloc_cb)(size_t, size_t)); +#endif + bool malloc_mutex_init(malloc_mutex_t *mutex) { + +#ifdef _WIN32 + if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, + _CRT_SPINCOUNT)) + return (true); +#elif (defined(JEMALLOC_OSSPIN)) + mutex->lock = 0; +#elif (defined(JEMALLOC_MUTEX_INIT_CB)) + if (postpone_init) { + mutex->postponed_next = postponed_mutexes; + postponed_mutexes = mutex; + } else { + if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) != + 0) + return (true); + } +#else pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) != 0) return (true); -#ifdef PTHREAD_MUTEX_ADAPTIVE_NP - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); -#else - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); -#endif - if (pthread_mutex_init(mutex, &attr) != 0) { + pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); + if (pthread_mutex_init(&mutex->lock, &attr) != 0) { pthread_mutexattr_destroy(&attr); return (true); } pthread_mutexattr_destroy(&attr); - +#endif return (false); } void -malloc_mutex_destroy(malloc_mutex_t *mutex) +malloc_mutex_prefork(malloc_mutex_t *mutex) { - if (pthread_mutex_destroy(mutex) != 0) { - malloc_write("<jemalloc>: Error in pthread_mutex_destroy()\n"); - abort(); + malloc_mutex_lock(mutex); +} + +void +malloc_mutex_postfork_parent(malloc_mutex_t *mutex) +{ + + malloc_mutex_unlock(mutex); +} + +void +malloc_mutex_postfork_child(malloc_mutex_t *mutex) +{ + +#ifdef JEMALLOC_MUTEX_INIT_CB + malloc_mutex_unlock(mutex); +#else + if (malloc_mutex_init(mutex)) { + malloc_printf("<jemalloc>: Error re-initializing mutex in " + "child\n"); + if (opt_abort) + abort(); } +#endif +} + +bool +mutex_boot(void) +{ + +#ifdef JEMALLOC_MUTEX_INIT_CB + postpone_init = false; + while (postponed_mutexes != NULL) { + if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, + base_calloc) != 0) + return (true); + postponed_mutexes = postponed_mutexes->postponed_next; + } +#endif + return (false); } diff --git a/dep/jemalloc/src/prof.c b/dep/jemalloc/src/prof.c index 636cccef52a..c133b95c2c6 100644 --- a/dep/jemalloc/src/prof.c +++ b/dep/jemalloc/src/prof.c @@ -1,41 +1,43 @@ #define JEMALLOC_PROF_C_ #include "jemalloc/internal/jemalloc_internal.h" -#ifdef JEMALLOC_PROF /******************************************************************************/ -#ifdef JEMALLOC_PROF_LIBGCC -#include <unwind.h> -#endif - #ifdef JEMALLOC_PROF_LIBUNWIND #define UNW_LOCAL_ONLY #include <libunwind.h> #endif +#ifdef JEMALLOC_PROF_LIBGCC +#include <unwind.h> +#endif + /******************************************************************************/ /* Data. */ +malloc_tsd_data(, prof_tdata, prof_tdata_t *, NULL) + bool opt_prof = false; bool opt_prof_active = true; -size_t opt_lg_prof_bt_max = LG_PROF_BT_MAX_DEFAULT; size_t opt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT; ssize_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT; bool opt_prof_gdump = false; +bool opt_prof_final = true; bool opt_prof_leak = false; -bool opt_prof_accum = true; -ssize_t opt_lg_prof_tcmax = LG_PROF_TCMAX_DEFAULT; +bool opt_prof_accum = false; char opt_prof_prefix[PATH_MAX + 1]; -uint64_t prof_interval; +uint64_t prof_interval = 0; bool prof_promote; -unsigned prof_bt_max; - -#ifndef NO_TLS -__thread prof_tdata_t *prof_tdata_tls - JEMALLOC_ATTR(tls_model("initial-exec")); -#endif -pthread_key_t prof_tdata_tsd; +/* + * Table of mutexes that are shared among ctx's. These are leaf locks, so + * there is no problem with using them for more than one ctx at the same time. + * The primary motivation for this sharing though is that ctx's are ephemeral, + * and destroying mutexes causes complications for systems that allocate when + * creating/destroying mutexes. + */ +static malloc_mutex_t *ctx_locks; +static unsigned cum_ctxs; /* Atomic counter. */ /* * Global hash of (prof_bt_t *)-->(prof_ctx_t *). This is the master data @@ -55,18 +57,13 @@ static uint64_t prof_dump_useq; * all profile dumps. The buffer is implicitly protected by bt2ctx_mtx, since * it must be locked anyway during dumping. */ -static char prof_dump_buf[PROF_DUMP_BUF_SIZE]; +static char prof_dump_buf[PROF_DUMP_BUFSIZE]; static unsigned prof_dump_buf_end; static int prof_dump_fd; /* Do not dump any profiles until bootstrapping is complete. */ static bool prof_booted = false; -static malloc_mutex_t enq_mtx; -static bool enq; -static bool enq_idump; -static bool enq_gdump; - /******************************************************************************/ /* Function prototypes for non-inline static functions. */ @@ -79,22 +76,23 @@ static _Unwind_Reason_Code prof_unwind_callback( struct _Unwind_Context *context, void *arg); #endif static bool prof_flush(bool propagate_err); -static bool prof_write(const char *s, bool propagate_err); +static bool prof_write(bool propagate_err, const char *s); +static bool prof_printf(bool propagate_err, const char *format, ...) + JEMALLOC_ATTR(format(printf, 2, 3)); static void prof_ctx_sum(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx); static void prof_ctx_destroy(prof_ctx_t *ctx); static void prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt); -static bool prof_dump_ctx(prof_ctx_t *ctx, prof_bt_t *bt, - bool propagate_err); +static bool prof_dump_ctx(bool propagate_err, prof_ctx_t *ctx, + prof_bt_t *bt); static bool prof_dump_maps(bool propagate_err); -static bool prof_dump(const char *filename, bool leakcheck, - bool propagate_err); +static bool prof_dump(bool propagate_err, const char *filename, + bool leakcheck); static void prof_dump_filename(char *filename, char v, int64_t vseq); static void prof_fdump(void); -static void prof_bt_hash(const void *key, unsigned minbits, size_t *hash1, - size_t *hash2); +static void prof_bt_hash(const void *key, size_t r_hash[2]); static bool prof_bt_keycomp(const void *k1, const void *k2); -static void prof_tdata_cleanup(void *arg); +static malloc_mutex_t *prof_ctx_mutex_choose(void); /******************************************************************************/ @@ -102,6 +100,8 @@ void bt_init(prof_bt_t *bt, void **vec) { + cassert(config_prof); + bt->vec = vec; bt->len = 0; } @@ -110,6 +110,8 @@ static void bt_destroy(prof_bt_t *bt) { + cassert(config_prof); + idalloc(bt); } @@ -118,6 +120,8 @@ bt_dup(prof_bt_t *bt) { prof_bt_t *ret; + cassert(config_prof); + /* * Create a single allocation that has space for vec immediately * following the prof_bt_t structure. The backtraces that get @@ -138,30 +142,32 @@ bt_dup(prof_bt_t *bt) } static inline void -prof_enter(void) +prof_enter(prof_tdata_t *prof_tdata) { - malloc_mutex_lock(&enq_mtx); - enq = true; - malloc_mutex_unlock(&enq_mtx); + cassert(config_prof); + + assert(prof_tdata->enq == false); + prof_tdata->enq = true; malloc_mutex_lock(&bt2ctx_mtx); } static inline void -prof_leave(void) +prof_leave(prof_tdata_t *prof_tdata) { bool idump, gdump; + cassert(config_prof); + malloc_mutex_unlock(&bt2ctx_mtx); - malloc_mutex_lock(&enq_mtx); - enq = false; - idump = enq_idump; - enq_idump = false; - gdump = enq_gdump; - enq_gdump = false; - malloc_mutex_unlock(&enq_mtx); + assert(prof_tdata->enq); + prof_tdata->enq = false; + idump = prof_tdata->enq_idump; + prof_tdata->enq_idump = false; + gdump = prof_tdata->enq_gdump; + prof_tdata->enq_gdump = false; if (idump) prof_idump(); @@ -169,50 +175,18 @@ prof_leave(void) prof_gdump(); } -#ifdef JEMALLOC_PROF_LIBGCC -static _Unwind_Reason_Code -prof_unwind_init_callback(struct _Unwind_Context *context, void *arg) -{ - - return (_URC_NO_REASON); -} - -static _Unwind_Reason_Code -prof_unwind_callback(struct _Unwind_Context *context, void *arg) -{ - prof_unwind_data_t *data = (prof_unwind_data_t *)arg; - - if (data->nignore > 0) - data->nignore--; - else { - data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context); - data->bt->len++; - if (data->bt->len == data->max) - return (_URC_END_OF_STACK); - } - - return (_URC_NO_REASON); -} - -void -prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) -{ - prof_unwind_data_t data = {bt, nignore, max}; - - _Unwind_Backtrace(prof_unwind_callback, &data); -} -#elif defined(JEMALLOC_PROF_LIBUNWIND) +#ifdef JEMALLOC_PROF_LIBUNWIND void -prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) +prof_backtrace(prof_bt_t *bt, unsigned nignore) { unw_context_t uc; unw_cursor_t cursor; unsigned i; int err; + cassert(config_prof); assert(bt->len == 0); assert(bt->vec != NULL); - assert(max <= (1U << opt_lg_prof_bt_max)); unw_getcontext(&uc); unw_init_local(&cursor, &uc); @@ -228,7 +202,7 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) * Iterate over stack frames until there are no more, or until no space * remains in bt. */ - for (i = 0; i < max; i++) { + for (i = 0; i < PROF_BT_MAX; i++) { unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]); bt->len++; err = unw_step(&cursor); @@ -236,12 +210,50 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) break; } } -#else +#elif (defined(JEMALLOC_PROF_LIBGCC)) +static _Unwind_Reason_Code +prof_unwind_init_callback(struct _Unwind_Context *context, void *arg) +{ + + cassert(config_prof); + + return (_URC_NO_REASON); +} + +static _Unwind_Reason_Code +prof_unwind_callback(struct _Unwind_Context *context, void *arg) +{ + prof_unwind_data_t *data = (prof_unwind_data_t *)arg; + + cassert(config_prof); + + if (data->nignore > 0) + data->nignore--; + else { + data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context); + data->bt->len++; + if (data->bt->len == data->max) + return (_URC_END_OF_STACK); + } + + return (_URC_NO_REASON); +} + +void +prof_backtrace(prof_bt_t *bt, unsigned nignore) +{ + prof_unwind_data_t data = {bt, nignore, PROF_BT_MAX}; + + cassert(config_prof); + + _Unwind_Backtrace(prof_unwind_callback, &data); +} +#elif (defined(JEMALLOC_PROF_GCC)) void -prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) +prof_backtrace(prof_bt_t *bt, unsigned nignore) { #define BT_FRAME(i) \ - if ((i) < nignore + max) { \ + if ((i) < nignore + PROF_BT_MAX) { \ void *p; \ if (__builtin_frame_address(i) == 0) \ return; \ @@ -255,8 +267,8 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) } else \ return; + cassert(config_prof); assert(nignore <= 3); - assert(max <= (1U << opt_lg_prof_bt_max)); BT_FRAME(0) BT_FRAME(1) @@ -405,6 +417,14 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) BT_FRAME(130) #undef BT_FRAME } +#else +void +prof_backtrace(prof_bt_t *bt, unsigned nignore) +{ + + cassert(config_prof); + assert(false); +} #endif prof_thr_cnt_t * @@ -416,12 +436,11 @@ prof_lookup(prof_bt_t *bt) } ret; prof_tdata_t *prof_tdata; - prof_tdata = PROF_TCACHE_GET(); - if (prof_tdata == NULL) { - prof_tdata = prof_tdata_init(); - if (prof_tdata == NULL) - return (NULL); - } + cassert(config_prof); + + prof_tdata = prof_tdata_get(false); + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + return (NULL); if (ckh_search(&prof_tdata->bt2cnt, bt, NULL, &ret.v)) { union { @@ -432,53 +451,57 @@ prof_lookup(prof_bt_t *bt) prof_ctx_t *p; void *v; } ctx; + bool new_ctx; /* * This thread's cache lacks bt. Look for it in the global * cache. */ - prof_enter(); + prof_enter(prof_tdata); if (ckh_search(&bt2ctx, bt, &btkey.v, &ctx.v)) { /* bt has never been seen before. Insert it. */ ctx.v = imalloc(sizeof(prof_ctx_t)); if (ctx.v == NULL) { - prof_leave(); + prof_leave(prof_tdata); return (NULL); } btkey.p = bt_dup(bt); if (btkey.v == NULL) { - prof_leave(); + prof_leave(prof_tdata); idalloc(ctx.v); return (NULL); } ctx.p->bt = btkey.p; - if (malloc_mutex_init(&ctx.p->lock)) { - prof_leave(); - idalloc(btkey.v); - idalloc(ctx.v); - return (NULL); - } + ctx.p->lock = prof_ctx_mutex_choose(); + /* + * Set nlimbo to 1, in order to avoid a race condition + * with prof_ctx_merge()/prof_ctx_destroy(). + */ + ctx.p->nlimbo = 1; memset(&ctx.p->cnt_merged, 0, sizeof(prof_cnt_t)); ql_new(&ctx.p->cnts_ql); if (ckh_insert(&bt2ctx, btkey.v, ctx.v)) { /* OOM. */ - prof_leave(); - malloc_mutex_destroy(&ctx.p->lock); + prof_leave(prof_tdata); idalloc(btkey.v); idalloc(ctx.v); return (NULL); } + new_ctx = true; + } else { + /* + * Increment nlimbo, in order to avoid a race condition + * with prof_ctx_merge()/prof_ctx_destroy(). + */ + malloc_mutex_lock(ctx.p->lock); + ctx.p->nlimbo++; + malloc_mutex_unlock(ctx.p->lock); + new_ctx = false; } - /* - * Acquire ctx's lock before releasing bt2ctx_mtx, in order to - * avoid a race condition with prof_ctx_destroy(). - */ - malloc_mutex_lock(&ctx.p->lock); - prof_leave(); + prof_leave(prof_tdata); /* Link a prof_thd_cnt_t into ctx for this thread. */ - if (opt_lg_prof_tcmax >= 0 && ckh_count(&prof_tdata->bt2cnt) - == (ZU(1) << opt_lg_prof_tcmax)) { + if (ckh_count(&prof_tdata->bt2cnt) == PROF_TCMAX) { assert(ckh_count(&prof_tdata->bt2cnt) > 0); /* * Flush the least recently used cnt in order to keep @@ -486,19 +509,19 @@ prof_lookup(prof_bt_t *bt) */ ret.p = ql_last(&prof_tdata->lru_ql, lru_link); assert(ret.v != NULL); - ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, NULL, - NULL); + if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, + NULL, NULL)) + assert(false); ql_remove(&prof_tdata->lru_ql, ret.p, lru_link); prof_ctx_merge(ret.p->ctx, ret.p); /* ret can now be re-used. */ } else { - assert(opt_lg_prof_tcmax < 0 || - ckh_count(&prof_tdata->bt2cnt) < (ZU(1) << - opt_lg_prof_tcmax)); + assert(ckh_count(&prof_tdata->bt2cnt) < PROF_TCMAX); /* Allocate and partially initialize a new cnt. */ ret.v = imalloc(sizeof(prof_thr_cnt_t)); if (ret.p == NULL) { - malloc_mutex_unlock(&ctx.p->lock); + if (new_ctx) + prof_ctx_destroy(ctx.p); return (NULL); } ql_elm_new(ret.p, cnts_link); @@ -509,13 +532,16 @@ prof_lookup(prof_bt_t *bt) ret.p->epoch = 0; memset(&ret.p->cnts, 0, sizeof(prof_cnt_t)); if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) { - malloc_mutex_unlock(&ctx.p->lock); + if (new_ctx) + prof_ctx_destroy(ctx.p); idalloc(ret.v); return (NULL); } ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link); + malloc_mutex_lock(ctx.p->lock); ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link); - malloc_mutex_unlock(&ctx.p->lock); + ctx.p->nlimbo--; + malloc_mutex_unlock(ctx.p->lock); } else { /* Move ret to the front of the LRU. */ ql_remove(&prof_tdata->lru_ql, ret.p, lru_link); @@ -531,6 +557,8 @@ prof_flush(bool propagate_err) bool ret = false; ssize_t err; + cassert(config_prof); + err = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end); if (err == -1) { if (propagate_err == false) { @@ -547,24 +575,26 @@ prof_flush(bool propagate_err) } static bool -prof_write(const char *s, bool propagate_err) +prof_write(bool propagate_err, const char *s) { unsigned i, slen, n; + cassert(config_prof); + i = 0; slen = strlen(s); while (i < slen) { /* Flush the buffer if it is full. */ - if (prof_dump_buf_end == PROF_DUMP_BUF_SIZE) + if (prof_dump_buf_end == PROF_DUMP_BUFSIZE) if (prof_flush(propagate_err) && propagate_err) return (true); - if (prof_dump_buf_end + slen <= PROF_DUMP_BUF_SIZE) { + if (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) { /* Finish writing. */ n = slen - i; } else { /* Write as much of s as will fit. */ - n = PROF_DUMP_BUF_SIZE - prof_dump_buf_end; + n = PROF_DUMP_BUFSIZE - prof_dump_buf_end; } memcpy(&prof_dump_buf[prof_dump_buf_end], &s[i], n); prof_dump_buf_end += n; @@ -574,13 +604,31 @@ prof_write(const char *s, bool propagate_err) return (false); } +JEMALLOC_ATTR(format(printf, 2, 3)) +static bool +prof_printf(bool propagate_err, const char *format, ...) +{ + bool ret; + va_list ap; + char buf[PROF_PRINTF_BUFSIZE]; + + va_start(ap, format); + malloc_vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + ret = prof_write(propagate_err, buf); + + return (ret); +} + static void prof_ctx_sum(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx) { prof_thr_cnt_t *thr_cnt; prof_cnt_t tcnt; - malloc_mutex_lock(&ctx->lock); + cassert(config_prof); + + malloc_mutex_lock(ctx->lock); memcpy(&ctx->cnt_summed, &ctx->cnt_merged, sizeof(prof_cnt_t)); ql_foreach(thr_cnt, &ctx->cnts_ql, cnts_link) { @@ -619,40 +667,48 @@ prof_ctx_sum(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx) cnt_all->accumbytes += ctx->cnt_summed.accumbytes; } - malloc_mutex_unlock(&ctx->lock); + malloc_mutex_unlock(ctx->lock); } static void prof_ctx_destroy(prof_ctx_t *ctx) { + prof_tdata_t *prof_tdata; + + cassert(config_prof); /* * Check that ctx is still unused by any thread cache before destroying - * it. prof_lookup() interlocks bt2ctx_mtx and ctx->lock in order to - * avoid a race condition with this function, and prof_ctx_merge() - * artificially raises ctx->cnt_merged.curobjs in order to avoid a race - * between the main body of prof_ctx_merge() and entry into this - * function. + * it. prof_lookup() increments ctx->nlimbo in order to avoid a race + * condition with this function, as does prof_ctx_merge() in order to + * avoid a race between the main body of prof_ctx_merge() and entry + * into this function. */ - prof_enter(); - malloc_mutex_lock(&ctx->lock); - if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 1) { + prof_tdata = prof_tdata_get(false); + assert((uintptr_t)prof_tdata > (uintptr_t)PROF_TDATA_STATE_MAX); + prof_enter(prof_tdata); + malloc_mutex_lock(ctx->lock); + if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 0 && + ctx->nlimbo == 1) { assert(ctx->cnt_merged.curbytes == 0); assert(ctx->cnt_merged.accumobjs == 0); assert(ctx->cnt_merged.accumbytes == 0); /* Remove ctx from bt2ctx. */ - ckh_remove(&bt2ctx, ctx->bt, NULL, NULL); - prof_leave(); + if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL)) + assert(false); + prof_leave(prof_tdata); /* Destroy ctx. */ - malloc_mutex_unlock(&ctx->lock); + malloc_mutex_unlock(ctx->lock); bt_destroy(ctx->bt); - malloc_mutex_destroy(&ctx->lock); idalloc(ctx); } else { - /* Compensate for increment in prof_ctx_merge(). */ - ctx->cnt_merged.curobjs--; - malloc_mutex_unlock(&ctx->lock); - prof_leave(); + /* + * Compensate for increment in prof_ctx_merge() or + * prof_lookup(). + */ + ctx->nlimbo--; + malloc_mutex_unlock(ctx->lock); + prof_leave(prof_tdata); } } @@ -661,20 +717,22 @@ prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt) { bool destroy; + cassert(config_prof); + /* Merge cnt stats and detach from ctx. */ - malloc_mutex_lock(&ctx->lock); + malloc_mutex_lock(ctx->lock); ctx->cnt_merged.curobjs += cnt->cnts.curobjs; ctx->cnt_merged.curbytes += cnt->cnts.curbytes; ctx->cnt_merged.accumobjs += cnt->cnts.accumobjs; ctx->cnt_merged.accumbytes += cnt->cnts.accumbytes; ql_remove(&ctx->cnts_ql, cnt, cnts_link); if (opt_prof_accum == false && ql_first(&ctx->cnts_ql) == NULL && - ctx->cnt_merged.curobjs == 0) { + ctx->cnt_merged.curobjs == 0 && ctx->nlimbo == 0) { /* - * Artificially raise ctx->cnt_merged.curobjs in order to keep - * another thread from winning the race to destroy ctx while - * this one has ctx->lock dropped. Without this, it would be - * possible for another thread to: + * Increment ctx->nlimbo in order to keep another thread from + * winning the race to destroy ctx while this one has ctx->lock + * dropped. Without this, it would be possible for another + * thread to: * * 1) Sample an allocation associated with ctx. * 2) Deallocate the sampled object. @@ -683,49 +741,51 @@ prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt) * The result would be that ctx no longer exists by the time * this thread accesses it in prof_ctx_destroy(). */ - ctx->cnt_merged.curobjs++; + ctx->nlimbo++; destroy = true; } else destroy = false; - malloc_mutex_unlock(&ctx->lock); + malloc_mutex_unlock(ctx->lock); if (destroy) prof_ctx_destroy(ctx); } static bool -prof_dump_ctx(prof_ctx_t *ctx, prof_bt_t *bt, bool propagate_err) +prof_dump_ctx(bool propagate_err, prof_ctx_t *ctx, prof_bt_t *bt) { - char buf[UMAX2S_BUFSIZE]; unsigned i; - if (opt_prof_accum == false && ctx->cnt_summed.curobjs == 0) { + cassert(config_prof); + + /* + * Current statistics can sum to 0 as a result of unmerged per thread + * statistics. Additionally, interval- and growth-triggered dumps can + * occur between the time a ctx is created and when its statistics are + * filled in. Avoid dumping any ctx that is an artifact of either + * implementation detail. + */ + if ((opt_prof_accum == false && ctx->cnt_summed.curobjs == 0) || + (opt_prof_accum && ctx->cnt_summed.accumobjs == 0)) { + assert(ctx->cnt_summed.curobjs == 0); assert(ctx->cnt_summed.curbytes == 0); assert(ctx->cnt_summed.accumobjs == 0); assert(ctx->cnt_summed.accumbytes == 0); return (false); } - if (prof_write(u2s(ctx->cnt_summed.curobjs, 10, buf), propagate_err) - || prof_write(": ", propagate_err) - || prof_write(u2s(ctx->cnt_summed.curbytes, 10, buf), - propagate_err) - || prof_write(" [", propagate_err) - || prof_write(u2s(ctx->cnt_summed.accumobjs, 10, buf), - propagate_err) - || prof_write(": ", propagate_err) - || prof_write(u2s(ctx->cnt_summed.accumbytes, 10, buf), - propagate_err) - || prof_write("] @", propagate_err)) + if (prof_printf(propagate_err, "%"PRId64": %"PRId64 + " [%"PRIu64": %"PRIu64"] @", + ctx->cnt_summed.curobjs, ctx->cnt_summed.curbytes, + ctx->cnt_summed.accumobjs, ctx->cnt_summed.accumbytes)) return (true); for (i = 0; i < bt->len; i++) { - if (prof_write(" 0x", propagate_err) - || prof_write(u2s((uintptr_t)bt->vec[i], 16, buf), - propagate_err)) + if (prof_printf(propagate_err, " %#"PRIxPTR, + (uintptr_t)bt->vec[i])) return (true); } - if (prof_write("\n", propagate_err)) + if (prof_write(propagate_err, "\n")) return (true); return (false); @@ -735,49 +795,29 @@ static bool prof_dump_maps(bool propagate_err) { int mfd; - char buf[UMAX2S_BUFSIZE]; - char *s; - unsigned i, slen; - /* /proc/<pid>/maps\0 */ - char mpath[6 + UMAX2S_BUFSIZE - + 5 + 1]; - - i = 0; - - s = "/proc/"; - slen = strlen(s); - memcpy(&mpath[i], s, slen); - i += slen; - - s = u2s(getpid(), 10, buf); - slen = strlen(s); - memcpy(&mpath[i], s, slen); - i += slen; - - s = "/maps"; - slen = strlen(s); - memcpy(&mpath[i], s, slen); - i += slen; + char filename[PATH_MAX + 1]; - mpath[i] = '\0'; + cassert(config_prof); - mfd = open(mpath, O_RDONLY); + malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps", + (int)getpid()); + mfd = open(filename, O_RDONLY); if (mfd != -1) { ssize_t nread; - if (prof_write("\nMAPPED_LIBRARIES:\n", propagate_err) && + if (prof_write(propagate_err, "\nMAPPED_LIBRARIES:\n") && propagate_err) return (true); nread = 0; do { prof_dump_buf_end += nread; - if (prof_dump_buf_end == PROF_DUMP_BUF_SIZE) { + if (prof_dump_buf_end == PROF_DUMP_BUFSIZE) { /* Make space in prof_dump_buf before read(). */ if (prof_flush(propagate_err) && propagate_err) return (true); } nread = read(mfd, &prof_dump_buf[prof_dump_buf_end], - PROF_DUMP_BUF_SIZE - prof_dump_buf_end); + PROF_DUMP_BUFSIZE - prof_dump_buf_end); } while (nread > 0); close(mfd); } else @@ -787,8 +827,9 @@ prof_dump_maps(bool propagate_err) } static bool -prof_dump(const char *filename, bool leakcheck, bool propagate_err) +prof_dump(bool propagate_err, const char *filename, bool leakcheck) { + prof_tdata_t *prof_tdata; prof_cnt_t cnt_all; size_t tabind; union { @@ -799,20 +840,24 @@ prof_dump(const char *filename, bool leakcheck, bool propagate_err) prof_ctx_t *p; void *v; } ctx; - char buf[UMAX2S_BUFSIZE]; size_t leak_nctx; - prof_enter(); + cassert(config_prof); + + prof_tdata = prof_tdata_get(false); + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + return (true); + prof_enter(prof_tdata); prof_dump_fd = creat(filename, 0644); if (prof_dump_fd == -1) { if (propagate_err == false) { - malloc_write("<jemalloc>: creat(\""); - malloc_write(filename); - malloc_write("\", 0644) failed\n"); + malloc_printf( + "<jemalloc>: creat(\"%s\"), 0644) failed\n", + filename); if (opt_abort) abort(); } - goto ERROR; + goto label_error; } /* Merge per thread profile stats, and sum them in cnt_all. */ @@ -822,131 +867,75 @@ prof_dump(const char *filename, bool leakcheck, bool propagate_err) prof_ctx_sum(ctx.p, &cnt_all, &leak_nctx); /* Dump profile header. */ - if (prof_write("heap profile: ", propagate_err) - || prof_write(u2s(cnt_all.curobjs, 10, buf), propagate_err) - || prof_write(": ", propagate_err) - || prof_write(u2s(cnt_all.curbytes, 10, buf), propagate_err) - || prof_write(" [", propagate_err) - || prof_write(u2s(cnt_all.accumobjs, 10, buf), propagate_err) - || prof_write(": ", propagate_err) - || prof_write(u2s(cnt_all.accumbytes, 10, buf), propagate_err)) - goto ERROR; - if (opt_lg_prof_sample == 0) { - if (prof_write("] @ heapprofile\n", propagate_err)) - goto ERROR; + if (prof_printf(propagate_err, + "heap profile: %"PRId64": %"PRId64 + " [%"PRIu64": %"PRIu64"] @ heapprofile\n", + cnt_all.curobjs, cnt_all.curbytes, + cnt_all.accumobjs, cnt_all.accumbytes)) + goto label_error; } else { - if (prof_write("] @ heap_v2/", propagate_err) - || prof_write(u2s((uint64_t)1U << opt_lg_prof_sample, 10, - buf), propagate_err) - || prof_write("\n", propagate_err)) - goto ERROR; + if (prof_printf(propagate_err, + "heap profile: %"PRId64": %"PRId64 + " [%"PRIu64": %"PRIu64"] @ heap_v2/%"PRIu64"\n", + cnt_all.curobjs, cnt_all.curbytes, + cnt_all.accumobjs, cnt_all.accumbytes, + ((uint64_t)1U << opt_lg_prof_sample))) + goto label_error; } /* Dump per ctx profile stats. */ for (tabind = 0; ckh_iter(&bt2ctx, &tabind, &bt.v, &ctx.v) == false;) { - if (prof_dump_ctx(ctx.p, bt.p, propagate_err)) - goto ERROR; + if (prof_dump_ctx(propagate_err, ctx.p, bt.p)) + goto label_error; } /* Dump /proc/<pid>/maps if possible. */ if (prof_dump_maps(propagate_err)) - goto ERROR; + goto label_error; if (prof_flush(propagate_err)) - goto ERROR; + goto label_error; close(prof_dump_fd); - prof_leave(); + prof_leave(prof_tdata); if (leakcheck && cnt_all.curbytes != 0) { - malloc_write("<jemalloc>: Leak summary: "); - malloc_write(u2s(cnt_all.curbytes, 10, buf)); - malloc_write((cnt_all.curbytes != 1) ? " bytes, " : " byte, "); - malloc_write(u2s(cnt_all.curobjs, 10, buf)); - malloc_write((cnt_all.curobjs != 1) ? " objects, " : - " object, "); - malloc_write(u2s(leak_nctx, 10, buf)); - malloc_write((leak_nctx != 1) ? " contexts\n" : " context\n"); - malloc_write("<jemalloc>: Run pprof on \""); - malloc_write(filename); - malloc_write("\" for leak detail\n"); + malloc_printf("<jemalloc>: Leak summary: %"PRId64" byte%s, %" + PRId64" object%s, %zu context%s\n", + cnt_all.curbytes, (cnt_all.curbytes != 1) ? "s" : "", + cnt_all.curobjs, (cnt_all.curobjs != 1) ? "s" : "", + leak_nctx, (leak_nctx != 1) ? "s" : ""); + malloc_printf( + "<jemalloc>: Run pprof on \"%s\" for leak detail\n", + filename); } return (false); -ERROR: - prof_leave(); +label_error: + prof_leave(prof_tdata); return (true); } -#define DUMP_FILENAME_BUFSIZE (PATH_MAX+ UMAX2S_BUFSIZE \ - + 1 \ - + UMAX2S_BUFSIZE \ - + 2 \ - + UMAX2S_BUFSIZE \ - + 5 + 1) +#define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1) static void prof_dump_filename(char *filename, char v, int64_t vseq) { - char buf[UMAX2S_BUFSIZE]; - char *s; - unsigned i, slen; - - /* - * Construct a filename of the form: - * - * <prefix>.<pid>.<seq>.v<vseq>.heap\0 - */ - i = 0; - - s = opt_prof_prefix; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = "."; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = u2s(getpid(), 10, buf); - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; + cassert(config_prof); - s = "."; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = u2s(prof_dump_seq, 10, buf); - prof_dump_seq++; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - s = "."; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - filename[i] = v; - i++; - - if (vseq != 0xffffffffffffffffLLU) { - s = u2s(vseq, 10, buf); - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; + if (vseq != UINT64_C(0xffffffffffffffff)) { + /* "<prefix>.<pid>.<seq>.v<vseq>.heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%d.%"PRIu64".%c%"PRId64".heap", + opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq); + } else { + /* "<prefix>.<pid>.<seq>.<v>.heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%d.%"PRIu64".%c.heap", + opt_prof_prefix, (int)getpid(), prof_dump_seq, v); } - - s = ".heap"; - slen = strlen(s); - memcpy(&filename[i], s, slen); - i += slen; - - filename[i] = '\0'; + prof_dump_seq++; } static void @@ -954,38 +943,43 @@ prof_fdump(void) { char filename[DUMP_FILENAME_BUFSIZE]; + cassert(config_prof); + if (prof_booted == false) return; - if (opt_prof_prefix[0] != '\0') { + if (opt_prof_final && opt_prof_prefix[0] != '\0') { malloc_mutex_lock(&prof_dump_seq_mtx); - prof_dump_filename(filename, 'f', 0xffffffffffffffffLLU); + prof_dump_filename(filename, 'f', UINT64_C(0xffffffffffffffff)); malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(filename, opt_prof_leak, false); + prof_dump(false, filename, opt_prof_leak); } } void prof_idump(void) { - char filename[DUMP_FILENAME_BUFSIZE]; + prof_tdata_t *prof_tdata; + char filename[PATH_MAX + 1]; + + cassert(config_prof); if (prof_booted == false) return; - malloc_mutex_lock(&enq_mtx); - if (enq) { - enq_idump = true; - malloc_mutex_unlock(&enq_mtx); + prof_tdata = prof_tdata_get(false); + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + return; + if (prof_tdata->enq) { + prof_tdata->enq_idump = true; return; } - malloc_mutex_unlock(&enq_mtx); if (opt_prof_prefix[0] != '\0') { malloc_mutex_lock(&prof_dump_seq_mtx); prof_dump_filename(filename, 'i', prof_dump_iseq); prof_dump_iseq++; malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(filename, false, false); + prof_dump(false, filename, false); } } @@ -994,6 +988,8 @@ prof_mdump(const char *filename) { char filename_buf[DUMP_FILENAME_BUFSIZE]; + cassert(config_prof); + if (opt_prof == false || prof_booted == false) return (true); @@ -1007,60 +1003,44 @@ prof_mdump(const char *filename) malloc_mutex_unlock(&prof_dump_seq_mtx); filename = filename_buf; } - return (prof_dump(filename, false, true)); + return (prof_dump(true, filename, false)); } void prof_gdump(void) { + prof_tdata_t *prof_tdata; char filename[DUMP_FILENAME_BUFSIZE]; + cassert(config_prof); + if (prof_booted == false) return; - malloc_mutex_lock(&enq_mtx); - if (enq) { - enq_gdump = true; - malloc_mutex_unlock(&enq_mtx); + prof_tdata = prof_tdata_get(false); + if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + return; + if (prof_tdata->enq) { + prof_tdata->enq_gdump = true; return; } - malloc_mutex_unlock(&enq_mtx); if (opt_prof_prefix[0] != '\0') { malloc_mutex_lock(&prof_dump_seq_mtx); prof_dump_filename(filename, 'u', prof_dump_useq); prof_dump_useq++; malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(filename, false, false); + prof_dump(false, filename, false); } } static void -prof_bt_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2) +prof_bt_hash(const void *key, size_t r_hash[2]) { - size_t ret1, ret2; - uint64_t h; prof_bt_t *bt = (prof_bt_t *)key; - assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64)); - assert(hash1 != NULL); - assert(hash2 != NULL); - - h = hash(bt->vec, bt->len * sizeof(void *), 0x94122f335b332aeaLLU); - if (minbits <= 32) { - /* - * Avoid doing multiple hashes, since a single hash provides - * enough bits. - */ - ret1 = h & ZU(0xffffffffU); - ret2 = h >> 32; - } else { - ret1 = h; - ret2 = hash(bt->vec, bt->len * sizeof(void *), - 0x8432a476666bbc13U); - } + cassert(config_prof); - *hash1 = ret1; - *hash2 = ret2; + hash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash); } static bool @@ -1069,16 +1049,28 @@ prof_bt_keycomp(const void *k1, const void *k2) const prof_bt_t *bt1 = (prof_bt_t *)k1; const prof_bt_t *bt2 = (prof_bt_t *)k2; + cassert(config_prof); + if (bt1->len != bt2->len) return (false); return (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0); } +static malloc_mutex_t * +prof_ctx_mutex_choose(void) +{ + unsigned nctxs = atomic_add_u(&cum_ctxs, 1); + + return (&ctx_locks[(nctxs - 1) % PROF_NCTX_LOCKS]); +} + prof_tdata_t * prof_tdata_init(void) { prof_tdata_t *prof_tdata; + cassert(config_prof); + /* Initialize an empty cache for this thread. */ prof_tdata = (prof_tdata_t *)imalloc(sizeof(prof_tdata_t)); if (prof_tdata == NULL) @@ -1091,52 +1083,68 @@ prof_tdata_init(void) } ql_new(&prof_tdata->lru_ql); - prof_tdata->vec = imalloc(sizeof(void *) * prof_bt_max); + prof_tdata->vec = imalloc(sizeof(void *) * PROF_BT_MAX); if (prof_tdata->vec == NULL) { - ckh_delete(&prof_tdata->bt2cnt); idalloc(prof_tdata); return (NULL); } - prof_tdata->prn_state = 0; + prof_tdata->prng_state = 0; prof_tdata->threshold = 0; prof_tdata->accum = 0; - PROF_TCACHE_SET(prof_tdata); + prof_tdata->enq = false; + prof_tdata->enq_idump = false; + prof_tdata->enq_gdump = false; + + prof_tdata_tsd_set(&prof_tdata); return (prof_tdata); } -static void +void prof_tdata_cleanup(void *arg) { - prof_tdata_t *prof_tdata; + prof_thr_cnt_t *cnt; + prof_tdata_t *prof_tdata = *(prof_tdata_t **)arg; - prof_tdata = PROF_TCACHE_GET(); - if (prof_tdata != NULL) { - prof_thr_cnt_t *cnt; + cassert(config_prof); + if (prof_tdata == PROF_TDATA_STATE_REINCARNATED) { + /* + * Another destructor deallocated memory after this destructor + * was called. Reset prof_tdata to PROF_TDATA_STATE_PURGATORY + * in order to receive another callback. + */ + prof_tdata = PROF_TDATA_STATE_PURGATORY; + prof_tdata_tsd_set(&prof_tdata); + } else if (prof_tdata == PROF_TDATA_STATE_PURGATORY) { + /* + * The previous time this destructor was called, we set the key + * to PROF_TDATA_STATE_PURGATORY so that other destructors + * wouldn't cause re-creation of the prof_tdata. This time, do + * nothing, so that the destructor will not be called again. + */ + } else if (prof_tdata != NULL) { /* * Delete the hash table. All of its contents can still be * iterated over via the LRU. */ ckh_delete(&prof_tdata->bt2cnt); - /* * Iteratively merge cnt's into the global stats and delete * them. */ while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) { - prof_ctx_merge(cnt->ctx, cnt); ql_remove(&prof_tdata->lru_ql, cnt, lru_link); + prof_ctx_merge(cnt->ctx, cnt); idalloc(cnt); } - idalloc(prof_tdata->vec); - idalloc(prof_tdata); - PROF_TCACHE_SET(NULL); + prof_tdata = PROF_TDATA_STATE_PURGATORY; + prof_tdata_tsd_set(&prof_tdata); } } @@ -1144,6 +1152,8 @@ void prof_boot0(void) { + cassert(config_prof); + memcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT, sizeof(PROF_PREFIX_DEFAULT)); } @@ -1152,6 +1162,8 @@ void prof_boot1(void) { + cassert(config_prof); + /* * opt_prof and prof_promote must be in their final state before any * arenas are initialized, so this function must be executed early. @@ -1164,50 +1176,53 @@ prof_boot1(void) */ opt_prof = true; opt_prof_gdump = false; - prof_interval = 0; } else if (opt_prof) { if (opt_lg_prof_interval >= 0) { prof_interval = (((uint64_t)1U) << opt_lg_prof_interval); - } else - prof_interval = 0; + } } - prof_promote = (opt_prof && opt_lg_prof_sample > PAGE_SHIFT); + prof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE); } bool prof_boot2(void) { + cassert(config_prof); + if (opt_prof) { + unsigned i; + if (ckh_new(&bt2ctx, PROF_CKH_MINITEMS, prof_bt_hash, prof_bt_keycomp)) return (true); if (malloc_mutex_init(&bt2ctx_mtx)) return (true); - if (pthread_key_create(&prof_tdata_tsd, prof_tdata_cleanup) - != 0) { + if (prof_tdata_tsd_boot()) { malloc_write( "<jemalloc>: Error in pthread_key_create()\n"); abort(); } - prof_bt_max = (1U << opt_lg_prof_bt_max); if (malloc_mutex_init(&prof_dump_seq_mtx)) return (true); - if (malloc_mutex_init(&enq_mtx)) - return (true); - enq = false; - enq_idump = false; - enq_gdump = false; - if (atexit(prof_fdump) != 0) { malloc_write("<jemalloc>: Error in atexit()\n"); if (opt_abort) abort(); } + + ctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS * + sizeof(malloc_mutex_t)); + if (ctx_locks == NULL) + return (true); + for (i = 0; i < PROF_NCTX_LOCKS; i++) { + if (malloc_mutex_init(&ctx_locks[i])) + return (true); + } } #ifdef JEMALLOC_PROF_LIBGCC @@ -1223,5 +1238,46 @@ prof_boot2(void) return (false); } +void +prof_prefork(void) +{ + + if (opt_prof) { + unsigned i; + + malloc_mutex_lock(&bt2ctx_mtx); + malloc_mutex_lock(&prof_dump_seq_mtx); + for (i = 0; i < PROF_NCTX_LOCKS; i++) + malloc_mutex_lock(&ctx_locks[i]); + } +} + +void +prof_postfork_parent(void) +{ + + if (opt_prof) { + unsigned i; + + for (i = 0; i < PROF_NCTX_LOCKS; i++) + malloc_mutex_postfork_parent(&ctx_locks[i]); + malloc_mutex_postfork_parent(&prof_dump_seq_mtx); + malloc_mutex_postfork_parent(&bt2ctx_mtx); + } +} + +void +prof_postfork_child(void) +{ + + if (opt_prof) { + unsigned i; + + for (i = 0; i < PROF_NCTX_LOCKS; i++) + malloc_mutex_postfork_child(&ctx_locks[i]); + malloc_mutex_postfork_child(&prof_dump_seq_mtx); + malloc_mutex_postfork_child(&bt2ctx_mtx); + } +} + /******************************************************************************/ -#endif /* JEMALLOC_PROF */ diff --git a/dep/jemalloc/src/quarantine.c b/dep/jemalloc/src/quarantine.c new file mode 100644 index 00000000000..f96a948d5c7 --- /dev/null +++ b/dep/jemalloc/src/quarantine.c @@ -0,0 +1,190 @@ +#define JEMALLOC_QUARANTINE_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +/* + * quarantine pointers close to NULL are used to encode state information that + * is used for cleaning up during thread shutdown. + */ +#define QUARANTINE_STATE_REINCARNATED ((quarantine_t *)(uintptr_t)1) +#define QUARANTINE_STATE_PURGATORY ((quarantine_t *)(uintptr_t)2) +#define QUARANTINE_STATE_MAX QUARANTINE_STATE_PURGATORY + +/******************************************************************************/ +/* Data. */ + +malloc_tsd_data(, quarantine, quarantine_t *, NULL) + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static quarantine_t *quarantine_grow(quarantine_t *quarantine); +static void quarantine_drain_one(quarantine_t *quarantine); +static void quarantine_drain(quarantine_t *quarantine, size_t upper_bound); + +/******************************************************************************/ + +quarantine_t * +quarantine_init(size_t lg_maxobjs) +{ + quarantine_t *quarantine; + + quarantine = (quarantine_t *)imalloc(offsetof(quarantine_t, objs) + + ((ZU(1) << lg_maxobjs) * sizeof(quarantine_obj_t))); + if (quarantine == NULL) + return (NULL); + quarantine->curbytes = 0; + quarantine->curobjs = 0; + quarantine->first = 0; + quarantine->lg_maxobjs = lg_maxobjs; + + quarantine_tsd_set(&quarantine); + + return (quarantine); +} + +static quarantine_t * +quarantine_grow(quarantine_t *quarantine) +{ + quarantine_t *ret; + + ret = quarantine_init(quarantine->lg_maxobjs + 1); + if (ret == NULL) { + quarantine_drain_one(quarantine); + return (quarantine); + } + + ret->curbytes = quarantine->curbytes; + ret->curobjs = quarantine->curobjs; + if (quarantine->first + quarantine->curobjs <= (ZU(1) << + quarantine->lg_maxobjs)) { + /* objs ring buffer data are contiguous. */ + memcpy(ret->objs, &quarantine->objs[quarantine->first], + quarantine->curobjs * sizeof(quarantine_obj_t)); + } else { + /* objs ring buffer data wrap around. */ + size_t ncopy_a = (ZU(1) << quarantine->lg_maxobjs) - + quarantine->first; + size_t ncopy_b = quarantine->curobjs - ncopy_a; + + memcpy(ret->objs, &quarantine->objs[quarantine->first], ncopy_a + * sizeof(quarantine_obj_t)); + memcpy(&ret->objs[ncopy_a], quarantine->objs, ncopy_b * + sizeof(quarantine_obj_t)); + } + idalloc(quarantine); + + return (ret); +} + +static void +quarantine_drain_one(quarantine_t *quarantine) +{ + quarantine_obj_t *obj = &quarantine->objs[quarantine->first]; + assert(obj->usize == isalloc(obj->ptr, config_prof)); + idalloc(obj->ptr); + quarantine->curbytes -= obj->usize; + quarantine->curobjs--; + quarantine->first = (quarantine->first + 1) & ((ZU(1) << + quarantine->lg_maxobjs) - 1); +} + +static void +quarantine_drain(quarantine_t *quarantine, size_t upper_bound) +{ + + while (quarantine->curbytes > upper_bound && quarantine->curobjs > 0) + quarantine_drain_one(quarantine); +} + +void +quarantine(void *ptr) +{ + quarantine_t *quarantine; + size_t usize = isalloc(ptr, config_prof); + + cassert(config_fill); + assert(opt_quarantine); + + quarantine = *quarantine_tsd_get(); + if ((uintptr_t)quarantine <= (uintptr_t)QUARANTINE_STATE_MAX) { + if (quarantine == QUARANTINE_STATE_PURGATORY) { + /* + * Make a note that quarantine() was called after + * quarantine_cleanup() was called. + */ + quarantine = QUARANTINE_STATE_REINCARNATED; + quarantine_tsd_set(&quarantine); + } + idalloc(ptr); + return; + } + /* + * Drain one or more objects if the quarantine size limit would be + * exceeded by appending ptr. + */ + if (quarantine->curbytes + usize > opt_quarantine) { + size_t upper_bound = (opt_quarantine >= usize) ? opt_quarantine + - usize : 0; + quarantine_drain(quarantine, upper_bound); + } + /* Grow the quarantine ring buffer if it's full. */ + if (quarantine->curobjs == (ZU(1) << quarantine->lg_maxobjs)) + quarantine = quarantine_grow(quarantine); + /* quarantine_grow() must free a slot if it fails to grow. */ + assert(quarantine->curobjs < (ZU(1) << quarantine->lg_maxobjs)); + /* Append ptr if its size doesn't exceed the quarantine size. */ + if (quarantine->curbytes + usize <= opt_quarantine) { + size_t offset = (quarantine->first + quarantine->curobjs) & + ((ZU(1) << quarantine->lg_maxobjs) - 1); + quarantine_obj_t *obj = &quarantine->objs[offset]; + obj->ptr = ptr; + obj->usize = usize; + quarantine->curbytes += usize; + quarantine->curobjs++; + if (opt_junk) + memset(ptr, 0x5a, usize); + } else { + assert(quarantine->curbytes == 0); + idalloc(ptr); + } +} + +void +quarantine_cleanup(void *arg) +{ + quarantine_t *quarantine = *(quarantine_t **)arg; + + if (quarantine == QUARANTINE_STATE_REINCARNATED) { + /* + * Another destructor deallocated memory after this destructor + * was called. Reset quarantine to QUARANTINE_STATE_PURGATORY + * in order to receive another callback. + */ + quarantine = QUARANTINE_STATE_PURGATORY; + quarantine_tsd_set(&quarantine); + } else if (quarantine == QUARANTINE_STATE_PURGATORY) { + /* + * The previous time this destructor was called, we set the key + * to QUARANTINE_STATE_PURGATORY so that other destructors + * wouldn't cause re-creation of the quarantine. This time, do + * nothing, so that the destructor will not be called again. + */ + } else if (quarantine != NULL) { + quarantine_drain(quarantine, 0); + idalloc(quarantine); + quarantine = QUARANTINE_STATE_PURGATORY; + quarantine_tsd_set(&quarantine); + } +} + +bool +quarantine_boot(void) +{ + + cassert(config_fill); + + if (quarantine_tsd_boot()) + return (true); + + return (false); +} diff --git a/dep/jemalloc/src/rtree.c b/dep/jemalloc/src/rtree.c index 7753743c5e6..90c6935a0ed 100644 --- a/dep/jemalloc/src/rtree.c +++ b/dep/jemalloc/src/rtree.c @@ -1,4 +1,4 @@ -#define RTREE_C_ +#define JEMALLOC_RTREE_C_ #include "jemalloc/internal/jemalloc_internal.h" rtree_t * @@ -20,7 +20,10 @@ rtree_new(unsigned bits) memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * height)); - malloc_mutex_init(&ret->mutex); + if (malloc_mutex_init(&ret->mutex)) { + /* Leak the rtree. */ + return (NULL); + } ret->height = height; if (bits_per_level * height > bits) ret->level2bits[0] = bits % bits_per_level; @@ -41,3 +44,24 @@ rtree_new(unsigned bits) return (ret); } + +void +rtree_prefork(rtree_t *rtree) +{ + + malloc_mutex_prefork(&rtree->mutex); +} + +void +rtree_postfork_parent(rtree_t *rtree) +{ + + malloc_mutex_postfork_parent(&rtree->mutex); +} + +void +rtree_postfork_child(rtree_t *rtree) +{ + + malloc_mutex_postfork_child(&rtree->mutex); +} diff --git a/dep/jemalloc/src/stats.c b/dep/jemalloc/src/stats.c index 3dfe0d232a6..43f87af6700 100644 --- a/dep/jemalloc/src/stats.c +++ b/dep/jemalloc/src/stats.c @@ -39,136 +39,40 @@ bool opt_stats_print = false; +size_t stats_cactive = 0; + /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -#ifdef JEMALLOC_STATS -static void malloc_vcprintf(void (*write_cb)(void *, const char *), - void *cbopaque, const char *format, va_list ap); static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i); static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i); static void stats_arena_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i); -#endif + void *cbopaque, unsigned i, bool bins, bool large); /******************************************************************************/ -/* - * We don't want to depend on vsnprintf() for production builds, since that can - * cause unnecessary bloat for static binaries. u2s() provides minimal integer - * printing functionality, so that malloc_printf() use can be limited to - * JEMALLOC_STATS code. - */ -char * -u2s(uint64_t x, unsigned base, char *s) -{ - unsigned i; - - i = UMAX2S_BUFSIZE - 1; - s[i] = '\0'; - switch (base) { - case 10: - do { - i--; - s[i] = "0123456789"[x % (uint64_t)10]; - x /= (uint64_t)10; - } while (x > 0); - break; - case 16: - do { - i--; - s[i] = "0123456789abcdef"[x & 0xf]; - x >>= 4; - } while (x > 0); - break; - default: - do { - i--; - s[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % - (uint64_t)base]; - x /= (uint64_t)base; - } while (x > 0); - } - - return (&s[i]); -} - -#ifdef JEMALLOC_STATS -static void -malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, - const char *format, va_list ap) -{ - char buf[4096]; - - if (write_cb == NULL) { - /* - * The caller did not provide an alternate write_cb callback - * function, so use the default one. malloc_write() is an - * inline function, so use malloc_message() directly here. - */ - write_cb = JEMALLOC_P(malloc_message); - cbopaque = NULL; - } - - vsnprintf(buf, sizeof(buf), format, ap); - write_cb(cbopaque, buf); -} - -/* - * Print to a callback function in such a way as to (hopefully) avoid memory - * allocation. - */ -JEMALLOC_ATTR(format(printf, 3, 4)) -void -malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, - const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - malloc_vcprintf(write_cb, cbopaque, format, ap); - va_end(ap); -} - -/* - * Print to stderr in such a way as to (hopefully) avoid memory allocation. - */ -JEMALLOC_ATTR(format(printf, 1, 2)) -void -malloc_printf(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - malloc_vcprintf(NULL, NULL, format, ap); - va_end(ap); -} -#endif - -#ifdef JEMALLOC_STATS static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { - size_t pagesize; + size_t page; bool config_tcache; unsigned nbins, j, gap_start; - CTL_GET("arenas.pagesize", &pagesize, size_t); + CTL_GET("arenas.page", &page, size_t); CTL_GET("config.tcache", &config_tcache, bool); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, - "bins: bin size regs pgs allocated nmalloc" + "bins: bin size regs pgs allocated nmalloc" " ndalloc nrequests nfills nflushes" - " newruns reruns maxruns curruns\n"); + " newruns reruns curruns\n"); } else { malloc_cprintf(write_cb, cbopaque, - "bins: bin size regs pgs allocated nmalloc" - " ndalloc newruns reruns maxruns" - " curruns\n"); + "bins: bin size regs pgs allocated nmalloc" + " ndalloc newruns reruns curruns\n"); } CTL_GET("arenas.nbins", &nbins, unsigned); for (j = 0, gap_start = UINT_MAX; j < nbins; j++) { @@ -179,12 +83,11 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, if (gap_start == UINT_MAX) gap_start = j; } else { - unsigned ntbins_, nqbins, ncbins, nsbins; size_t reg_size, run_size, allocated; uint32_t nregs; uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; uint64_t reruns; - size_t highruns, curruns; + size_t curruns; if (gap_start != UINT_MAX) { if (j > gap_start + 1) { @@ -199,10 +102,6 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, } gap_start = UINT_MAX; } - CTL_GET("arenas.ntbins", &ntbins_, unsigned); - CTL_GET("arenas.nqbins", &nqbins, unsigned); - CTL_GET("arenas.ncbins", &ncbins, unsigned); - CTL_GET("arenas.nsbins", &nsbins, unsigned); CTL_J_GET("arenas.bin.0.size", ®_size, size_t); CTL_J_GET("arenas.bin.0.nregs", &nregs, uint32_t); CTL_J_GET("arenas.bin.0.run_size", &run_size, size_t); @@ -222,36 +121,25 @@ stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, } CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.highruns", &highruns, - size_t); CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns, size_t); if (config_tcache) { malloc_cprintf(write_cb, cbopaque, - "%13u %1s %5zu %4u %3zu %12zu %12"PRIu64 + "%13u %5zu %4u %3zu %12zu %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu %12zu\n", - j, - j < ntbins_ ? "T" : j < ntbins_ + nqbins ? - "Q" : j < ntbins_ + nqbins + ncbins ? "C" : - "S", - reg_size, nregs, run_size / pagesize, + " %12zu\n", + j, reg_size, nregs, run_size / page, allocated, nmalloc, ndalloc, nrequests, - nfills, nflushes, nruns, reruns, highruns, - curruns); + nfills, nflushes, nruns, reruns, curruns); } else { malloc_cprintf(write_cb, cbopaque, - "%13u %1s %5zu %4u %3zu %12zu %12"PRIu64 + "%13u %5zu %4u %3zu %12zu %12"PRIu64 " %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu %12zu\n", - j, - j < ntbins_ ? "T" : j < ntbins_ + nqbins ? - "Q" : j < ntbins_ + nqbins + ncbins ? "C" : - "S", - reg_size, nregs, run_size / pagesize, + " %12zu\n", + j, reg_size, nregs, run_size / page, allocated, nmalloc, ndalloc, nruns, reruns, - highruns, curruns); + curruns); } } } @@ -271,18 +159,18 @@ static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, unsigned i) { - size_t pagesize, nlruns, j; + size_t page, nlruns, j; ssize_t gap_start; - CTL_GET("arenas.pagesize", &pagesize, size_t); + CTL_GET("arenas.page", &page, size_t); malloc_cprintf(write_cb, cbopaque, "large: size pages nmalloc ndalloc nrequests" - " maxruns curruns\n"); + " curruns\n"); CTL_GET("arenas.nlruns", &nlruns, size_t); for (j = 0, gap_start = -1; j < nlruns; j++) { uint64_t nmalloc, ndalloc, nrequests; - size_t run_size, highruns, curruns; + size_t run_size, curruns; CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc, uint64_t); @@ -295,8 +183,6 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, gap_start = j; } else { CTL_J_GET("arenas.lrun.0.size", &run_size, size_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.highruns", &highruns, - size_t); CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns, size_t); if (gap_start != -1) { @@ -306,9 +192,9 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, } malloc_cprintf(write_cb, cbopaque, "%13zu %5zu %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu %12zu\n", - run_size, run_size / pagesize, nmalloc, ndalloc, - nrequests, highruns, curruns); + " %12zu\n", + run_size, run_size / page, nmalloc, ndalloc, + nrequests, curruns); } } if (gap_start != -1) @@ -317,17 +203,25 @@ stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, static void stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i) + unsigned i, bool bins, bool large) { - size_t pagesize, pactive, pdirty, mapped; + unsigned nthreads; + const char *dss; + size_t page, pactive, pdirty, mapped; uint64_t npurge, nmadvise, purged; size_t small_allocated; uint64_t small_nmalloc, small_ndalloc, small_nrequests; size_t large_allocated; uint64_t large_nmalloc, large_ndalloc, large_nrequests; - CTL_GET("arenas.pagesize", &pagesize, size_t); + CTL_GET("arenas.page", &page, size_t); + CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned); + malloc_cprintf(write_cb, cbopaque, + "assigned threads: %u\n", nthreads); + CTL_I_GET("stats.arenas.0.dss", &dss, const char *); + malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n", + dss); CTL_I_GET("stats.arenas.0.pactive", &pactive, size_t); CTL_I_GET("stats.arenas.0.pdirty", &pdirty, size_t); CTL_I_GET("stats.arenas.0.npurge", &npurge, uint64_t); @@ -361,15 +255,15 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, small_nmalloc + large_nmalloc, small_ndalloc + large_ndalloc, small_nrequests + large_nrequests); - malloc_cprintf(write_cb, cbopaque, "active: %12zu\n", - pactive * pagesize ); + malloc_cprintf(write_cb, cbopaque, "active: %12zu\n", pactive * page); CTL_I_GET("stats.arenas.0.mapped", &mapped, size_t); malloc_cprintf(write_cb, cbopaque, "mapped: %12zu\n", mapped); - stats_arena_bins_print(write_cb, cbopaque, i); - stats_arena_lruns_print(write_cb, cbopaque, i); + if (bins) + stats_arena_bins_print(write_cb, cbopaque, i); + if (large) + stats_arena_lruns_print(write_cb, cbopaque, i); } -#endif void stats_print(void (*write_cb)(void *, const char *), void *cbopaque, @@ -378,7 +272,6 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, int err; uint64_t epoch; size_t u64sz; - char s[UMAX2S_BUFSIZE]; bool general = true; bool merged = true; bool unmerged = true; @@ -394,8 +287,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, * */ epoch = 1; u64sz = sizeof(uint64_t); - err = JEMALLOC_P(mallctl)("epoch", &epoch, &u64sz, &epoch, - sizeof(uint64_t)); + err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t)); if (err != 0) { if (err == EAGAIN) { malloc_write("<jemalloc>: Memory allocation failure in " @@ -407,42 +299,33 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, abort(); } - if (write_cb == NULL) { - /* - * The caller did not provide an alternate write_cb callback - * function, so use the default one. malloc_write() is an - * inline function, so use malloc_message() directly here. - */ - write_cb = JEMALLOC_P(malloc_message); - cbopaque = NULL; - } - if (opts != NULL) { unsigned i; for (i = 0; opts[i] != '\0'; i++) { switch (opts[i]) { - case 'g': - general = false; - break; - case 'm': - merged = false; - break; - case 'a': - unmerged = false; - break; - case 'b': - bins = false; - break; - case 'l': - large = false; - break; - default:; + case 'g': + general = false; + break; + case 'm': + merged = false; + break; + case 'a': + unmerged = false; + break; + case 'b': + bins = false; + break; + case 'l': + large = false; + break; + default:; } } } - write_cb(cbopaque, "___ Begin jemalloc statistics ___\n"); + malloc_cprintf(write_cb, cbopaque, + "___ Begin jemalloc statistics ___\n"); if (general) { int err; const char *cpv; @@ -457,256 +340,146 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, cpsz = sizeof(const char *); CTL_GET("version", &cpv, const char *); - write_cb(cbopaque, "Version: "); - write_cb(cbopaque, cpv); - write_cb(cbopaque, "\n"); + malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv); CTL_GET("config.debug", &bv, bool); - write_cb(cbopaque, "Assertions "); - write_cb(cbopaque, bv ? "enabled" : "disabled"); - write_cb(cbopaque, "\n"); + malloc_cprintf(write_cb, cbopaque, "Assertions %s\n", + bv ? "enabled" : "disabled"); #define OPT_WRITE_BOOL(n) \ - if ((err = JEMALLOC_P(mallctl)("opt."#n, &bv, &bsz, \ - NULL, 0)) == 0) { \ - write_cb(cbopaque, " opt."#n": "); \ - write_cb(cbopaque, bv ? "true" : "false"); \ - write_cb(cbopaque, "\n"); \ + if ((err = je_mallctl("opt."#n, &bv, &bsz, NULL, 0)) \ + == 0) { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %s\n", bv ? "true" : "false"); \ } #define OPT_WRITE_SIZE_T(n) \ - if ((err = JEMALLOC_P(mallctl)("opt."#n, &sv, &ssz, \ - NULL, 0)) == 0) { \ - write_cb(cbopaque, " opt."#n": "); \ - write_cb(cbopaque, u2s(sv, 10, s)); \ - write_cb(cbopaque, "\n"); \ + if ((err = je_mallctl("opt."#n, &sv, &ssz, NULL, 0)) \ + == 0) { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %zu\n", sv); \ } #define OPT_WRITE_SSIZE_T(n) \ - if ((err = JEMALLOC_P(mallctl)("opt."#n, &ssv, &sssz, \ - NULL, 0)) == 0) { \ - if (ssv >= 0) { \ - write_cb(cbopaque, " opt."#n": "); \ - write_cb(cbopaque, u2s(ssv, 10, s)); \ - } else { \ - write_cb(cbopaque, " opt."#n": -"); \ - write_cb(cbopaque, u2s(-ssv, 10, s)); \ - } \ - write_cb(cbopaque, "\n"); \ + if ((err = je_mallctl("opt."#n, &ssv, &sssz, NULL, 0)) \ + == 0) { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %zd\n", ssv); \ } #define OPT_WRITE_CHAR_P(n) \ - if ((err = JEMALLOC_P(mallctl)("opt."#n, &cpv, &cpsz, \ - NULL, 0)) == 0) { \ - write_cb(cbopaque, " opt."#n": \""); \ - write_cb(cbopaque, cpv); \ - write_cb(cbopaque, "\"\n"); \ + if ((err = je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0)) \ + == 0) { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": \"%s\"\n", cpv); \ } - write_cb(cbopaque, "Run-time option settings:\n"); + malloc_cprintf(write_cb, cbopaque, + "Run-time option settings:\n"); OPT_WRITE_BOOL(abort) - OPT_WRITE_SIZE_T(lg_qspace_max) - OPT_WRITE_SIZE_T(lg_cspace_max) OPT_WRITE_SIZE_T(lg_chunk) + OPT_WRITE_CHAR_P(dss) OPT_WRITE_SIZE_T(narenas) OPT_WRITE_SSIZE_T(lg_dirty_mult) OPT_WRITE_BOOL(stats_print) OPT_WRITE_BOOL(junk) + OPT_WRITE_SIZE_T(quarantine) + OPT_WRITE_BOOL(redzone) OPT_WRITE_BOOL(zero) - OPT_WRITE_BOOL(sysv) + OPT_WRITE_BOOL(utrace) + OPT_WRITE_BOOL(valgrind) OPT_WRITE_BOOL(xmalloc) OPT_WRITE_BOOL(tcache) - OPT_WRITE_SSIZE_T(lg_tcache_gc_sweep) OPT_WRITE_SSIZE_T(lg_tcache_max) OPT_WRITE_BOOL(prof) OPT_WRITE_CHAR_P(prof_prefix) - OPT_WRITE_SIZE_T(lg_prof_bt_max) OPT_WRITE_BOOL(prof_active) OPT_WRITE_SSIZE_T(lg_prof_sample) OPT_WRITE_BOOL(prof_accum) - OPT_WRITE_SSIZE_T(lg_prof_tcmax) OPT_WRITE_SSIZE_T(lg_prof_interval) OPT_WRITE_BOOL(prof_gdump) + OPT_WRITE_BOOL(prof_final) OPT_WRITE_BOOL(prof_leak) - OPT_WRITE_BOOL(overcommit) #undef OPT_WRITE_BOOL #undef OPT_WRITE_SIZE_T #undef OPT_WRITE_SSIZE_T #undef OPT_WRITE_CHAR_P - write_cb(cbopaque, "CPUs: "); - write_cb(cbopaque, u2s(ncpus, 10, s)); - write_cb(cbopaque, "\n"); + malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus); CTL_GET("arenas.narenas", &uv, unsigned); - write_cb(cbopaque, "Max arenas: "); - write_cb(cbopaque, u2s(uv, 10, s)); - write_cb(cbopaque, "\n"); + malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); - write_cb(cbopaque, "Pointer size: "); - write_cb(cbopaque, u2s(sizeof(void *), 10, s)); - write_cb(cbopaque, "\n"); + malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n", + sizeof(void *)); CTL_GET("arenas.quantum", &sv, size_t); - write_cb(cbopaque, "Quantum size: "); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "\n"); - - CTL_GET("arenas.cacheline", &sv, size_t); - write_cb(cbopaque, "Cacheline size (assumed): "); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "\n"); - - CTL_GET("arenas.subpage", &sv, size_t); - write_cb(cbopaque, "Subpage spacing: "); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "\n"); - - if ((err = JEMALLOC_P(mallctl)("arenas.tspace_min", &sv, &ssz, - NULL, 0)) == 0) { - write_cb(cbopaque, "Tiny 2^n-spaced sizes: ["); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ".."); - - CTL_GET("arenas.tspace_max", &sv, size_t); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "]\n"); - } + malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv); - CTL_GET("arenas.qspace_min", &sv, size_t); - write_cb(cbopaque, "Quantum-spaced sizes: ["); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ".."); - CTL_GET("arenas.qspace_max", &sv, size_t); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "]\n"); - - CTL_GET("arenas.cspace_min", &sv, size_t); - write_cb(cbopaque, "Cacheline-spaced sizes: ["); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ".."); - CTL_GET("arenas.cspace_max", &sv, size_t); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "]\n"); - - CTL_GET("arenas.sspace_min", &sv, size_t); - write_cb(cbopaque, "Subpage-spaced sizes: ["); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ".."); - CTL_GET("arenas.sspace_max", &sv, size_t); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "]\n"); + CTL_GET("arenas.page", &sv, size_t); + malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); CTL_GET("opt.lg_dirty_mult", &ssv, ssize_t); if (ssv >= 0) { - write_cb(cbopaque, - "Min active:dirty page ratio per arena: "); - write_cb(cbopaque, u2s((1U << ssv), 10, s)); - write_cb(cbopaque, ":1\n"); + malloc_cprintf(write_cb, cbopaque, + "Min active:dirty page ratio per arena: %u:1\n", + (1U << ssv)); } else { - write_cb(cbopaque, + malloc_cprintf(write_cb, cbopaque, "Min active:dirty page ratio per arena: N/A\n"); } - if ((err = JEMALLOC_P(mallctl)("arenas.tcache_max", &sv, - &ssz, NULL, 0)) == 0) { - write_cb(cbopaque, - "Maximum thread-cached size class: "); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, "\n"); - } - if ((err = JEMALLOC_P(mallctl)("opt.lg_tcache_gc_sweep", &ssv, - &ssz, NULL, 0)) == 0) { - size_t tcache_gc_sweep = (1U << ssv); - bool tcache_enabled; - CTL_GET("opt.tcache", &tcache_enabled, bool); - write_cb(cbopaque, "Thread cache GC sweep interval: "); - write_cb(cbopaque, tcache_enabled && ssv >= 0 ? - u2s(tcache_gc_sweep, 10, s) : "N/A"); - write_cb(cbopaque, "\n"); + if ((err = je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0)) + == 0) { + malloc_cprintf(write_cb, cbopaque, + "Maximum thread-cached size class: %zu\n", sv); } - if ((err = JEMALLOC_P(mallctl)("opt.prof", &bv, &bsz, NULL, 0)) - == 0 && bv) { - CTL_GET("opt.lg_prof_bt_max", &sv, size_t); - write_cb(cbopaque, "Maximum profile backtrace depth: "); - write_cb(cbopaque, u2s((1U << sv), 10, s)); - write_cb(cbopaque, "\n"); - - CTL_GET("opt.lg_prof_tcmax", &ssv, ssize_t); - write_cb(cbopaque, - "Maximum per thread backtrace cache: "); - if (ssv >= 0) { - write_cb(cbopaque, u2s((1U << ssv), 10, s)); - write_cb(cbopaque, " (2^"); - write_cb(cbopaque, u2s(ssv, 10, s)); - write_cb(cbopaque, ")\n"); - } else - write_cb(cbopaque, "N/A\n"); - + if ((err = je_mallctl("opt.prof", &bv, &bsz, NULL, 0)) == 0 && + bv) { CTL_GET("opt.lg_prof_sample", &sv, size_t); - write_cb(cbopaque, "Average profile sample interval: "); - write_cb(cbopaque, u2s((((uint64_t)1U) << sv), 10, s)); - write_cb(cbopaque, " (2^"); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ")\n"); + malloc_cprintf(write_cb, cbopaque, + "Average profile sample interval: %"PRIu64 + " (2^%zu)\n", (((uint64_t)1U) << sv), sv); CTL_GET("opt.lg_prof_interval", &ssv, ssize_t); - write_cb(cbopaque, "Average profile dump interval: "); if (ssv >= 0) { - write_cb(cbopaque, u2s((((uint64_t)1U) << ssv), - 10, s)); - write_cb(cbopaque, " (2^"); - write_cb(cbopaque, u2s(ssv, 10, s)); - write_cb(cbopaque, ")\n"); - } else - write_cb(cbopaque, "N/A\n"); + malloc_cprintf(write_cb, cbopaque, + "Average profile dump interval: %"PRIu64 + " (2^%zd)\n", + (((uint64_t)1U) << ssv), ssv); + } else { + malloc_cprintf(write_cb, cbopaque, + "Average profile dump interval: N/A\n"); + } } - CTL_GET("arenas.chunksize", &sv, size_t); - write_cb(cbopaque, "Chunk size: "); - write_cb(cbopaque, u2s(sv, 10, s)); CTL_GET("opt.lg_chunk", &sv, size_t); - write_cb(cbopaque, " (2^"); - write_cb(cbopaque, u2s(sv, 10, s)); - write_cb(cbopaque, ")\n"); + malloc_cprintf(write_cb, cbopaque, "Chunk size: %zu (2^%zu)\n", + (ZU(1) << sv), sv); } -#ifdef JEMALLOC_STATS - { - int err; - size_t ssz; + if (config_stats) { + size_t *cactive; size_t allocated, active, mapped; - size_t chunks_current, chunks_high, swap_avail; + size_t chunks_current, chunks_high; uint64_t chunks_total; size_t huge_allocated; uint64_t huge_nmalloc, huge_ndalloc; - ssz = sizeof(size_t); - + CTL_GET("stats.cactive", &cactive, size_t *); CTL_GET("stats.allocated", &allocated, size_t); CTL_GET("stats.active", &active, size_t); CTL_GET("stats.mapped", &mapped, size_t); malloc_cprintf(write_cb, cbopaque, - "Allocated: %zu, active: %zu, mapped: %zu\n", allocated, - active, mapped); + "Allocated: %zu, active: %zu, mapped: %zu\n", + allocated, active, mapped); + malloc_cprintf(write_cb, cbopaque, + "Current active ceiling: %zu\n", atomic_read_z(cactive)); /* Print chunk stats. */ CTL_GET("stats.chunks.total", &chunks_total, uint64_t); CTL_GET("stats.chunks.high", &chunks_high, size_t); CTL_GET("stats.chunks.current", &chunks_current, size_t); - if ((err = JEMALLOC_P(mallctl)("swap.avail", &swap_avail, &ssz, - NULL, 0)) == 0) { - size_t lg_chunk; - - malloc_cprintf(write_cb, cbopaque, "chunks: nchunks " - "highchunks curchunks swap_avail\n"); - CTL_GET("opt.lg_chunk", &lg_chunk, size_t); - malloc_cprintf(write_cb, cbopaque, - " %13"PRIu64"%13zu%13zu%13zu\n", - chunks_total, chunks_high, chunks_current, - swap_avail << lg_chunk); - } else { - malloc_cprintf(write_cb, cbopaque, "chunks: nchunks " - "highchunks curchunks\n"); - malloc_cprintf(write_cb, cbopaque, - " %13"PRIu64"%13zu%13zu\n", - chunks_total, chunks_high, chunks_current); - } + malloc_cprintf(write_cb, cbopaque, "chunks: nchunks " + "highchunks curchunks\n"); + malloc_cprintf(write_cb, cbopaque, + " %13"PRIu64" %12zu %12zu\n", + chunks_total, chunks_high, chunks_current); /* Print huge stats. */ CTL_GET("stats.huge.nmalloc", &huge_nmalloc, uint64_t); @@ -723,11 +496,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_GET("arenas.narenas", &narenas, unsigned); { - bool initialized[narenas]; + VARIABLE_ARRAY(bool, initialized, narenas); size_t isz; unsigned i, ninitialized; - isz = sizeof(initialized); + isz = sizeof(bool) * narenas; xmallctl("arenas.initialized", initialized, &isz, NULL, 0); for (i = ninitialized = 0; i < narenas; i++) { @@ -735,12 +508,12 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, ninitialized++; } - if (ninitialized > 1) { + if (ninitialized > 1 || unmerged == false) { /* Print merged arena stats. */ malloc_cprintf(write_cb, cbopaque, "\nMerged arenas stats:\n"); stats_arena_print(write_cb, cbopaque, - narenas); + narenas, bins, large); } } } @@ -752,11 +525,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, CTL_GET("arenas.narenas", &narenas, unsigned); { - bool initialized[narenas]; + VARIABLE_ARRAY(bool, initialized, narenas); size_t isz; unsigned i; - isz = sizeof(initialized); + isz = sizeof(bool) * narenas; xmallctl("arenas.initialized", initialized, &isz, NULL, 0); @@ -766,12 +539,11 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, cbopaque, "\narenas[%u]:\n", i); stats_arena_print(write_cb, - cbopaque, i); + cbopaque, i, bins, large); } } } } } -#endif /* #ifdef JEMALLOC_STATS */ - write_cb(cbopaque, "--- End jemalloc statistics ---\n"); + malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n"); } diff --git a/dep/jemalloc/src/tcache.c b/dep/jemalloc/src/tcache.c index cbbe7a113a9..98ed19edd52 100644 --- a/dep/jemalloc/src/tcache.c +++ b/dep/jemalloc/src/tcache.c @@ -1,105 +1,131 @@ #define JEMALLOC_TCACHE_C_ #include "jemalloc/internal/jemalloc_internal.h" -#ifdef JEMALLOC_TCACHE + /******************************************************************************/ /* Data. */ +malloc_tsd_data(, tcache, tcache_t *, NULL) +malloc_tsd_data(, tcache_enabled, tcache_enabled_t, tcache_enabled_default) + bool opt_tcache = true; ssize_t opt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT; -ssize_t opt_lg_tcache_gc_sweep = LG_TCACHE_GC_SWEEP_DEFAULT; - -/* Map of thread-specific caches. */ -#ifndef NO_TLS -__thread tcache_t *tcache_tls JEMALLOC_ATTR(tls_model("initial-exec")); -#endif -/* - * Same contents as tcache, but initialized such that the TSD destructor is - * called when a thread exits, so that the cache can be cleaned up. - */ -pthread_key_t tcache_tsd; +tcache_bin_info_t *tcache_bin_info; +static unsigned stack_nelms; /* Total stack elms per tcache. */ -size_t nhbins; -size_t tcache_maxclass; -unsigned tcache_gc_incr; +size_t nhbins; +size_t tcache_maxclass; /******************************************************************************/ -/* Function prototypes for non-inline static functions. */ -static void tcache_thread_cleanup(void *arg); +size_t tcache_salloc(const void *ptr) +{ -/******************************************************************************/ + return (arena_salloc(ptr, false)); +} + +void +tcache_event_hard(tcache_t *tcache) +{ + size_t binind = tcache->next_gc_bin; + tcache_bin_t *tbin = &tcache->tbins[binind]; + tcache_bin_info_t *tbin_info = &tcache_bin_info[binind]; + + if (tbin->low_water > 0) { + /* + * Flush (ceiling) 3/4 of the objects below the low water mark. + */ + if (binind < NBINS) { + tcache_bin_flush_small(tbin, binind, tbin->ncached - + tbin->low_water + (tbin->low_water >> 2), tcache); + } else { + tcache_bin_flush_large(tbin, binind, tbin->ncached - + tbin->low_water + (tbin->low_water >> 2), tcache); + } + /* + * Reduce fill count by 2X. Limit lg_fill_div such that the + * fill count is always at least 1. + */ + if ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1) + tbin->lg_fill_div++; + } else if (tbin->low_water < 0) { + /* + * Increase fill count by 2X. Make sure lg_fill_div stays + * greater than 0. + */ + if (tbin->lg_fill_div > 1) + tbin->lg_fill_div--; + } + tbin->low_water = tbin->ncached; + + tcache->next_gc_bin++; + if (tcache->next_gc_bin == nhbins) + tcache->next_gc_bin = 0; + tcache->ev_cnt = 0; +} void * tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind) { void *ret; - arena_tcache_fill_small(tcache->arena, tbin, binind -#ifdef JEMALLOC_PROF - , tcache->prof_accumbytes -#endif - ); -#ifdef JEMALLOC_PROF - tcache->prof_accumbytes = 0; -#endif + arena_tcache_fill_small(tcache->arena, tbin, binind, + config_prof ? tcache->prof_accumbytes : 0); + if (config_prof) + tcache->prof_accumbytes = 0; ret = tcache_alloc_easy(tbin); return (ret); } void -tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache_t *tcache -#endif - ) +tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem, + tcache_t *tcache) { - void *flush, *deferred, *ptr; + void *ptr; unsigned i, nflush, ndeferred; - bool first_pass; + bool merged_stats = false; - assert(binind < nbins); + assert(binind < NBINS); assert(rem <= tbin->ncached); - assert(tbin->ncached > 0 || tbin->avail == NULL); - for (flush = tbin->avail, nflush = tbin->ncached - rem, first_pass = - true; flush != NULL; flush = deferred, nflush = ndeferred) { + for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) { /* Lock the arena bin associated with the first object. */ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(flush); + arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE( + tbin->avail[0]); arena_t *arena = chunk->arena; arena_bin_t *bin = &arena->bins[binind]; -#ifdef JEMALLOC_PROF - if (arena == tcache->arena) { - malloc_mutex_lock(&arena->lock); - arena_prof_accum(arena, tcache->prof_accumbytes); - malloc_mutex_unlock(&arena->lock); + if (config_prof && arena == tcache->arena) { + if (arena_prof_accum(arena, tcache->prof_accumbytes)) + prof_idump(); tcache->prof_accumbytes = 0; } -#endif malloc_mutex_lock(&bin->lock); -#ifdef JEMALLOC_STATS - if (arena == tcache->arena) { + if (config_stats && arena == tcache->arena) { + assert(merged_stats == false); + merged_stats = true; bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; } -#endif - deferred = NULL; ndeferred = 0; for (i = 0; i < nflush; i++) { - ptr = flush; + ptr = tbin->avail[i]; assert(ptr != NULL); - flush = *(void **)ptr; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk->arena == arena) { size_t pageind = ((uintptr_t)ptr - - (uintptr_t)chunk) >> PAGE_SHIFT; + (uintptr_t)chunk) >> LG_PAGE; arena_chunk_map_t *mapelm = - &chunk->map[pageind-map_bias]; - arena_dalloc_bin(arena, chunk, ptr, mapelm); + arena_mapp_get(chunk, pageind); + if (config_fill && opt_junk) { + arena_alloc_junk_small(ptr, + &arena_bin_info[binind], true); + } + arena_dalloc_bin_locked(arena, chunk, ptr, + mapelm); } else { /* * This object was allocated via a different @@ -107,71 +133,75 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem * locked. Stash the object, so that it can be * handled in a future pass. */ - *(void **)ptr = deferred; - deferred = ptr; + tbin->avail[ndeferred] = ptr; ndeferred++; } } malloc_mutex_unlock(&bin->lock); - - if (first_pass) { - tbin->avail = flush; - first_pass = false; - } + } + if (config_stats && merged_stats == false) { + /* + * The flush loop didn't happen to flush to this thread's + * arena, so the stats didn't get merged. Manually do so now. + */ + arena_bin_t *bin = &tcache->arena->bins[binind]; + malloc_mutex_lock(&bin->lock); + bin->stats.nflushes++; + bin->stats.nrequests += tbin->tstats.nrequests; + tbin->tstats.nrequests = 0; + malloc_mutex_unlock(&bin->lock); } + memmove(tbin->avail, &tbin->avail[tbin->ncached - rem], + rem * sizeof(void *)); tbin->ncached = rem; - if (tbin->ncached < tbin->low_water) + if ((int)tbin->ncached < tbin->low_water) tbin->low_water = tbin->ncached; } void -tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache_t *tcache -#endif - ) +tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem, + tcache_t *tcache) { - void *flush, *deferred, *ptr; + void *ptr; unsigned i, nflush, ndeferred; - bool first_pass; + bool merged_stats = false; assert(binind < nhbins); assert(rem <= tbin->ncached); - assert(tbin->ncached > 0 || tbin->avail == NULL); - for (flush = tbin->avail, nflush = tbin->ncached - rem, first_pass = - true; flush != NULL; flush = deferred, nflush = ndeferred) { + for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) { /* Lock the arena associated with the first object. */ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(flush); + arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE( + tbin->avail[0]); arena_t *arena = chunk->arena; + UNUSED bool idump; + if (config_prof) + idump = false; malloc_mutex_lock(&arena->lock); -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) - if (arena == tcache->arena) { -#endif -#ifdef JEMALLOC_PROF - arena_prof_accum(arena, tcache->prof_accumbytes); - tcache->prof_accumbytes = 0; -#endif -#ifdef JEMALLOC_STATS - arena->stats.nrequests_large += tbin->tstats.nrequests; - arena->stats.lstats[binind - nbins].nrequests += - tbin->tstats.nrequests; - tbin->tstats.nrequests = 0; -#endif -#if (defined(JEMALLOC_PROF) || defined(JEMALLOC_STATS)) + if ((config_prof || config_stats) && arena == tcache->arena) { + if (config_prof) { + idump = arena_prof_accum_locked(arena, + tcache->prof_accumbytes); + tcache->prof_accumbytes = 0; + } + if (config_stats) { + merged_stats = true; + arena->stats.nrequests_large += + tbin->tstats.nrequests; + arena->stats.lstats[binind - NBINS].nrequests += + tbin->tstats.nrequests; + tbin->tstats.nrequests = 0; + } } -#endif - deferred = NULL; ndeferred = 0; for (i = 0; i < nflush; i++) { - ptr = flush; + ptr = tbin->avail[i]; assert(ptr != NULL); - flush = *(void **)ptr; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk->arena == arena) - arena_dalloc_large(arena, chunk, ptr); + arena_dalloc_large_locked(arena, chunk, ptr); else { /* * This object was allocated via a different @@ -179,32 +209,74 @@ tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem * Stash the object, so that it can be handled * in a future pass. */ - *(void **)ptr = deferred; - deferred = ptr; + tbin->avail[ndeferred] = ptr; ndeferred++; } } malloc_mutex_unlock(&arena->lock); - - if (first_pass) { - tbin->avail = flush; - first_pass = false; - } + if (config_prof && idump) + prof_idump(); + } + if (config_stats && merged_stats == false) { + /* + * The flush loop didn't happen to flush to this thread's + * arena, so the stats didn't get merged. Manually do so now. + */ + arena_t *arena = tcache->arena; + malloc_mutex_lock(&arena->lock); + arena->stats.nrequests_large += tbin->tstats.nrequests; + arena->stats.lstats[binind - NBINS].nrequests += + tbin->tstats.nrequests; + tbin->tstats.nrequests = 0; + malloc_mutex_unlock(&arena->lock); } + memmove(tbin->avail, &tbin->avail[tbin->ncached - rem], + rem * sizeof(void *)); tbin->ncached = rem; - if (tbin->ncached < tbin->low_water) + if ((int)tbin->ncached < tbin->low_water) tbin->low_water = tbin->ncached; } +void +tcache_arena_associate(tcache_t *tcache, arena_t *arena) +{ + + if (config_stats) { + /* Link into list of extant tcaches. */ + malloc_mutex_lock(&arena->lock); + ql_elm_new(tcache, link); + ql_tail_insert(&arena->tcache_ql, tcache, link); + malloc_mutex_unlock(&arena->lock); + } + tcache->arena = arena; +} + +void +tcache_arena_dissociate(tcache_t *tcache) +{ + + if (config_stats) { + /* Unlink from list of extant tcaches. */ + malloc_mutex_lock(&tcache->arena->lock); + ql_remove(&tcache->arena->tcache_ql, tcache, link); + malloc_mutex_unlock(&tcache->arena->lock); + tcache_stats_merge(tcache, tcache->arena); + } +} + tcache_t * tcache_create(arena_t *arena) { tcache_t *tcache; - size_t size; + size_t size, stack_offset; unsigned i; size = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins); + /* Naturally align the pointer stacks. */ + size = PTR_CEILING(size); + stack_offset = size; + size += stack_nelms * sizeof(void *); /* * Round up to the nearest multiple of the cacheline size, in order to * avoid the possibility of false cacheline sharing. @@ -215,35 +287,27 @@ tcache_create(arena_t *arena) */ size = (size + CACHELINE_MASK) & (-CACHELINE); - if (size <= small_maxclass) + if (size <= SMALL_MAXCLASS) tcache = (tcache_t *)arena_malloc_small(arena, size, true); + else if (size <= tcache_maxclass) + tcache = (tcache_t *)arena_malloc_large(arena, size, true); else - tcache = (tcache_t *)icalloc(size); + tcache = (tcache_t *)icallocx(size, false, arena); if (tcache == NULL) return (NULL); -#ifdef JEMALLOC_STATS - /* Link into list of extant tcaches. */ - malloc_mutex_lock(&arena->lock); - ql_elm_new(tcache, link); - ql_tail_insert(&arena->tcache_ql, tcache, link); - malloc_mutex_unlock(&arena->lock); -#endif + tcache_arena_associate(tcache, arena); - tcache->arena = arena; assert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0); - for (i = 0; i < nbins; i++) { - if ((arena->bins[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) { - tcache->tbins[i].ncached_max = (arena->bins[i].nregs << - 1); - } else - tcache->tbins[i].ncached_max = TCACHE_NSLOTS_SMALL_MAX; + for (i = 0; i < nhbins; i++) { + tcache->tbins[i].lg_fill_div = 1; + tcache->tbins[i].avail = (void **)((uintptr_t)tcache + + (uintptr_t)stack_offset); + stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); } - for (; i < nhbins; i++) - tcache->tbins[i].ncached_max = TCACHE_NSLOTS_LARGE; - TCACHE_SET(tcache); + tcache_tsd_set(&tcache); return (tcache); } @@ -252,114 +316,96 @@ void tcache_destroy(tcache_t *tcache) { unsigned i; + size_t tcache_size; -#ifdef JEMALLOC_STATS - /* Unlink from list of extant tcaches. */ - malloc_mutex_lock(&tcache->arena->lock); - ql_remove(&tcache->arena->tcache_ql, tcache, link); - malloc_mutex_unlock(&tcache->arena->lock); - tcache_stats_merge(tcache, tcache->arena); -#endif + tcache_arena_dissociate(tcache); - for (i = 0; i < nbins; i++) { + for (i = 0; i < NBINS; i++) { tcache_bin_t *tbin = &tcache->tbins[i]; - tcache_bin_flush_small(tbin, i, 0 -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); - -#ifdef JEMALLOC_STATS - if (tbin->tstats.nrequests != 0) { + tcache_bin_flush_small(tbin, i, 0, tcache); + + if (config_stats && tbin->tstats.nrequests != 0) { arena_t *arena = tcache->arena; arena_bin_t *bin = &arena->bins[i]; malloc_mutex_lock(&bin->lock); bin->stats.nrequests += tbin->tstats.nrequests; malloc_mutex_unlock(&bin->lock); } -#endif } for (; i < nhbins; i++) { tcache_bin_t *tbin = &tcache->tbins[i]; - tcache_bin_flush_large(tbin, i, 0 -#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF)) - , tcache -#endif - ); - -#ifdef JEMALLOC_STATS - if (tbin->tstats.nrequests != 0) { + tcache_bin_flush_large(tbin, i, 0, tcache); + + if (config_stats && tbin->tstats.nrequests != 0) { arena_t *arena = tcache->arena; malloc_mutex_lock(&arena->lock); arena->stats.nrequests_large += tbin->tstats.nrequests; - arena->stats.lstats[i - nbins].nrequests += + arena->stats.lstats[i - NBINS].nrequests += tbin->tstats.nrequests; malloc_mutex_unlock(&arena->lock); } -#endif } -#ifdef JEMALLOC_PROF - if (tcache->prof_accumbytes > 0) { - malloc_mutex_lock(&tcache->arena->lock); - arena_prof_accum(tcache->arena, tcache->prof_accumbytes); - malloc_mutex_unlock(&tcache->arena->lock); - } -#endif + if (config_prof && tcache->prof_accumbytes > 0 && + arena_prof_accum(tcache->arena, tcache->prof_accumbytes)) + prof_idump(); - if (arena_salloc(tcache) <= small_maxclass) { + tcache_size = arena_salloc(tcache, false); + if (tcache_size <= SMALL_MAXCLASS) { arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache); arena_t *arena = chunk->arena; size_t pageind = ((uintptr_t)tcache - (uintptr_t)chunk) >> - PAGE_SHIFT; - arena_chunk_map_t *mapelm = &chunk->map[pageind-map_bias]; - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - (mapelm->bits >> PAGE_SHIFT)) << - PAGE_SHIFT)); - arena_bin_t *bin = run->bin; + LG_PAGE; + arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); - malloc_mutex_lock(&bin->lock); - arena_dalloc_bin(arena, chunk, tcache, mapelm); - malloc_mutex_unlock(&bin->lock); + arena_dalloc_bin(arena, chunk, tcache, pageind, mapelm); + } else if (tcache_size <= tcache_maxclass) { + arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache); + arena_t *arena = chunk->arena; + + arena_dalloc_large(arena, chunk, tcache); } else - idalloc(tcache); + idallocx(tcache, false); } -static void +void tcache_thread_cleanup(void *arg) { - tcache_t *tcache = (tcache_t *)arg; + tcache_t *tcache = *(tcache_t **)arg; - if (tcache == (void *)(uintptr_t)1) { + if (tcache == TCACHE_STATE_DISABLED) { + /* Do nothing. */ + } else if (tcache == TCACHE_STATE_REINCARNATED) { /* - * The previous time this destructor was called, we set the key - * to 1 so that other destructors wouldn't cause re-creation of - * the tcache. This time, do nothing, so that the destructor - * will not be called again. + * Another destructor called an allocator function after this + * destructor was called. Reset tcache to + * TCACHE_STATE_PURGATORY in order to receive another callback. */ - } else if (tcache == (void *)(uintptr_t)2) { + tcache = TCACHE_STATE_PURGATORY; + tcache_tsd_set(&tcache); + } else if (tcache == TCACHE_STATE_PURGATORY) { /* - * Another destructor called an allocator function after this - * destructor was called. Reset tcache to 1 in order to - * receive another callback. + * The previous time this destructor was called, we set the key + * to TCACHE_STATE_PURGATORY so that other destructors wouldn't + * cause re-creation of the tcache. This time, do nothing, so + * that the destructor will not be called again. */ - TCACHE_SET((uintptr_t)1); } else if (tcache != NULL) { - assert(tcache != (void *)(uintptr_t)1); + assert(tcache != TCACHE_STATE_PURGATORY); tcache_destroy(tcache); - TCACHE_SET((uintptr_t)1); + tcache = TCACHE_STATE_PURGATORY; + tcache_tsd_set(&tcache); } } -#ifdef JEMALLOC_STATS void tcache_stats_merge(tcache_t *tcache, arena_t *arena) { unsigned i; /* Merge and reset tcache stats. */ - for (i = 0; i < nbins; i++) { + for (i = 0; i < NBINS; i++) { arena_bin_t *bin = &arena->bins[i]; tcache_bin_t *tbin = &tcache->tbins[i]; malloc_mutex_lock(&bin->lock); @@ -369,49 +415,62 @@ tcache_stats_merge(tcache_t *tcache, arena_t *arena) } for (; i < nhbins; i++) { - malloc_large_stats_t *lstats = &arena->stats.lstats[i - nbins]; + malloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS]; tcache_bin_t *tbin = &tcache->tbins[i]; arena->stats.nrequests_large += tbin->tstats.nrequests; lstats->nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; } } -#endif -void -tcache_boot(void) +bool +tcache_boot0(void) { + unsigned i; - if (opt_tcache) { - /* - * If necessary, clamp opt_lg_tcache_max, now that - * small_maxclass and arena_maxclass are known. - */ - if (opt_lg_tcache_max < 0 || (1U << - opt_lg_tcache_max) < small_maxclass) - tcache_maxclass = small_maxclass; - else if ((1U << opt_lg_tcache_max) > arena_maxclass) - tcache_maxclass = arena_maxclass; - else - tcache_maxclass = (1U << opt_lg_tcache_max); - - nhbins = nbins + (tcache_maxclass >> PAGE_SHIFT); - - /* Compute incremental GC event threshold. */ - if (opt_lg_tcache_gc_sweep >= 0) { - tcache_gc_incr = ((1U << opt_lg_tcache_gc_sweep) / - nbins) + (((1U << opt_lg_tcache_gc_sweep) % nbins == - 0) ? 0 : 1); - } else - tcache_gc_incr = 0; - - if (pthread_key_create(&tcache_tsd, tcache_thread_cleanup) != - 0) { - malloc_write( - "<jemalloc>: Error in pthread_key_create()\n"); - abort(); + /* + * If necessary, clamp opt_lg_tcache_max, now that arena_maxclass is + * known. + */ + if (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS) + tcache_maxclass = SMALL_MAXCLASS; + else if ((1U << opt_lg_tcache_max) > arena_maxclass) + tcache_maxclass = arena_maxclass; + else + tcache_maxclass = (1U << opt_lg_tcache_max); + + nhbins = NBINS + (tcache_maxclass >> LG_PAGE); + + /* Initialize tcache_bin_info. */ + tcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins * + sizeof(tcache_bin_info_t)); + if (tcache_bin_info == NULL) + return (true); + stack_nelms = 0; + for (i = 0; i < NBINS; i++) { + if ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) { + tcache_bin_info[i].ncached_max = + (arena_bin_info[i].nregs << 1); + } else { + tcache_bin_info[i].ncached_max = + TCACHE_NSLOTS_SMALL_MAX; } + stack_nelms += tcache_bin_info[i].ncached_max; + } + for (; i < nhbins; i++) { + tcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE; + stack_nelms += tcache_bin_info[i].ncached_max; } + + return (false); +} + +bool +tcache_boot1(void) +{ + + if (tcache_tsd_boot() || tcache_enabled_tsd_boot()) + return (true); + + return (false); } -/******************************************************************************/ -#endif /* JEMALLOC_TCACHE */ diff --git a/dep/jemalloc/src/tsd.c b/dep/jemalloc/src/tsd.c new file mode 100644 index 00000000000..961a546329c --- /dev/null +++ b/dep/jemalloc/src/tsd.c @@ -0,0 +1,107 @@ +#define JEMALLOC_TSD_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +/******************************************************************************/ +/* Data. */ + +static unsigned ncleanups; +static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX]; + +/******************************************************************************/ + +void * +malloc_tsd_malloc(size_t size) +{ + + /* Avoid choose_arena() in order to dodge bootstrapping issues. */ + return (arena_malloc(arenas[0], size, false, false)); +} + +void +malloc_tsd_dalloc(void *wrapper) +{ + + idalloc(wrapper); +} + +void +malloc_tsd_no_cleanup(void *arg) +{ + + not_reached(); +} + +#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32) +#ifndef _WIN32 +JEMALLOC_EXPORT +#endif +void +_malloc_thread_cleanup(void) +{ + bool pending[MALLOC_TSD_CLEANUPS_MAX], again; + unsigned i; + + for (i = 0; i < ncleanups; i++) + pending[i] = true; + + do { + again = false; + for (i = 0; i < ncleanups; i++) { + if (pending[i]) { + pending[i] = cleanups[i](); + if (pending[i]) + again = true; + } + } + } while (again); +} +#endif + +void +malloc_tsd_cleanup_register(bool (*f)(void)) +{ + + assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX); + cleanups[ncleanups] = f; + ncleanups++; +} + +void +malloc_tsd_boot(void) +{ + + ncleanups = 0; +} + +#ifdef _WIN32 +static BOOL WINAPI +_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + + switch (fdwReason) { +#ifdef JEMALLOC_LAZY_LOCK + case DLL_THREAD_ATTACH: + isthreaded = true; + break; +#endif + case DLL_THREAD_DETACH: + _malloc_thread_cleanup(); + break; + default: + break; + } + return (true); +} + +#ifdef _MSC_VER +# ifdef _M_IX86 +# pragma comment(linker, "/INCLUDE:__tls_used") +# else +# pragma comment(linker, "/INCLUDE:_tls_used") +# endif +# pragma section(".CRT$XLY",long,read) +#endif +JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used) +static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL, + DWORD fdwReason, LPVOID lpvReserved) = _tls_callback; +#endif diff --git a/dep/jemalloc/src/util.c b/dep/jemalloc/src/util.c new file mode 100644 index 00000000000..b3a01143698 --- /dev/null +++ b/dep/jemalloc/src/util.c @@ -0,0 +1,641 @@ +#define assert(e) do { \ + if (config_debug && !(e)) { \ + malloc_write("<jemalloc>: Failed assertion\n"); \ + abort(); \ + } \ +} while (0) + +#define not_reached() do { \ + if (config_debug) { \ + malloc_write("<jemalloc>: Unreachable code reached\n"); \ + abort(); \ + } \ +} while (0) + +#define not_implemented() do { \ + if (config_debug) { \ + malloc_write("<jemalloc>: Not implemented\n"); \ + abort(); \ + } \ +} while (0) + +#define JEMALLOC_UTIL_C_ +#include "jemalloc/internal/jemalloc_internal.h" + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static void wrtmessage(void *cbopaque, const char *s); +#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1) +static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s, + size_t *slen_p); +#define D2S_BUFSIZE (1 + U2S_BUFSIZE) +static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p); +#define O2S_BUFSIZE (1 + U2S_BUFSIZE) +static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p); +#define X2S_BUFSIZE (2 + U2S_BUFSIZE) +static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, + size_t *slen_p); + +/******************************************************************************/ + +/* malloc_message() setup. */ +static void +wrtmessage(void *cbopaque, const char *s) +{ + +#ifdef SYS_write + /* + * Use syscall(2) rather than write(2) when possible in order to avoid + * the possibility of memory allocation within libc. This is necessary + * on FreeBSD; most operating systems do not have this problem though. + */ + UNUSED int result = syscall(SYS_write, STDERR_FILENO, s, strlen(s)); +#else + UNUSED int result = write(STDERR_FILENO, s, strlen(s)); +#endif +} + +JEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s); + +/* + * Wrapper around malloc_message() that avoids the need for + * je_malloc_message(...) throughout the code. + */ +void +malloc_write(const char *s) +{ + + if (je_malloc_message != NULL) + je_malloc_message(NULL, s); + else + wrtmessage(NULL, s); +} + +/* + * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so + * provide a wrapper. + */ +int +buferror(char *buf, size_t buflen) +{ + +#ifdef _WIN32 + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + (LPSTR)buf, buflen, NULL); + return (0); +#elif defined(_GNU_SOURCE) + char *b = strerror_r(errno, buf, buflen); + if (b != buf) { + strncpy(buf, b, buflen); + buf[buflen-1] = '\0'; + } + return (0); +#else + return (strerror_r(errno, buf, buflen)); +#endif +} + +uintmax_t +malloc_strtoumax(const char *nptr, char **endptr, int base) +{ + uintmax_t ret, digit; + int b; + bool neg; + const char *p, *ns; + + if (base < 0 || base == 1 || base > 36) { + set_errno(EINVAL); + return (UINTMAX_MAX); + } + b = base; + + /* Swallow leading whitespace and get sign, if any. */ + neg = false; + p = nptr; + while (true) { + switch (*p) { + case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': + p++; + break; + case '-': + neg = true; + /* Fall through. */ + case '+': + p++; + /* Fall through. */ + default: + goto label_prefix; + } + } + + /* Get prefix, if any. */ + label_prefix: + /* + * Note where the first non-whitespace/sign character is so that it is + * possible to tell whether any digits are consumed (e.g., " 0" vs. + * " -x"). + */ + ns = p; + if (*p == '0') { + switch (p[1]) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': + if (b == 0) + b = 8; + if (b == 8) + p++; + break; + case 'x': + switch (p[2]) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': + if (b == 0) + b = 16; + if (b == 16) + p += 2; + break; + default: + break; + } + break; + default: + break; + } + } + if (b == 0) + b = 10; + + /* Convert. */ + ret = 0; + while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b) + || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b) + || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) { + uintmax_t pret = ret; + ret *= b; + ret += digit; + if (ret < pret) { + /* Overflow. */ + set_errno(ERANGE); + return (UINTMAX_MAX); + } + p++; + } + if (neg) + ret = -ret; + + if (endptr != NULL) { + if (p == ns) { + /* No characters were converted. */ + *endptr = (char *)nptr; + } else + *endptr = (char *)p; + } + + return (ret); +} + +static char * +u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) +{ + unsigned i; + + i = U2S_BUFSIZE - 1; + s[i] = '\0'; + switch (base) { + case 10: + do { + i--; + s[i] = "0123456789"[x % (uint64_t)10]; + x /= (uint64_t)10; + } while (x > 0); + break; + case 16: { + const char *digits = (uppercase) + ? "0123456789ABCDEF" + : "0123456789abcdef"; + + do { + i--; + s[i] = digits[x & 0xf]; + x >>= 4; + } while (x > 0); + break; + } default: { + const char *digits = (uppercase) + ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + : "0123456789abcdefghijklmnopqrstuvwxyz"; + + assert(base >= 2 && base <= 36); + do { + i--; + s[i] = digits[x % (uint64_t)base]; + x /= (uint64_t)base; + } while (x > 0); + }} + + *slen_p = U2S_BUFSIZE - 1 - i; + return (&s[i]); +} + +static char * +d2s(intmax_t x, char sign, char *s, size_t *slen_p) +{ + bool neg; + + if ((neg = (x < 0))) + x = -x; + s = u2s(x, 10, false, s, slen_p); + if (neg) + sign = '-'; + switch (sign) { + case '-': + if (neg == false) + break; + /* Fall through. */ + case ' ': + case '+': + s--; + (*slen_p)++; + *s = sign; + break; + default: not_reached(); + } + return (s); +} + +static char * +o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) +{ + + s = u2s(x, 8, false, s, slen_p); + if (alt_form && *s != '0') { + s--; + (*slen_p)++; + *s = '0'; + } + return (s); +} + +static char * +x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) +{ + + s = u2s(x, 16, uppercase, s, slen_p); + if (alt_form) { + s -= 2; + (*slen_p) += 2; + memcpy(s, uppercase ? "0X" : "0x", 2); + } + return (s); +} + +int +malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + int ret; + size_t i; + const char *f; + +#define APPEND_C(c) do { \ + if (i < size) \ + str[i] = (c); \ + i++; \ +} while (0) +#define APPEND_S(s, slen) do { \ + if (i < size) { \ + size_t cpylen = (slen <= size - i) ? slen : size - i; \ + memcpy(&str[i], s, cpylen); \ + } \ + i += slen; \ +} while (0) +#define APPEND_PADDED_S(s, slen, width, left_justify) do { \ + /* Left padding. */ \ + size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ? \ + (size_t)width - slen : 0); \ + if (left_justify == false && pad_len != 0) { \ + size_t j; \ + for (j = 0; j < pad_len; j++) \ + APPEND_C(' '); \ + } \ + /* Value. */ \ + APPEND_S(s, slen); \ + /* Right padding. */ \ + if (left_justify && pad_len != 0) { \ + size_t j; \ + for (j = 0; j < pad_len; j++) \ + APPEND_C(' '); \ + } \ +} while (0) +#define GET_ARG_NUMERIC(val, len) do { \ + switch (len) { \ + case '?': \ + val = va_arg(ap, int); \ + break; \ + case '?' | 0x80: \ + val = va_arg(ap, unsigned int); \ + break; \ + case 'l': \ + val = va_arg(ap, long); \ + break; \ + case 'l' | 0x80: \ + val = va_arg(ap, unsigned long); \ + break; \ + case 'q': \ + val = va_arg(ap, long long); \ + break; \ + case 'q' | 0x80: \ + val = va_arg(ap, unsigned long long); \ + break; \ + case 'j': \ + val = va_arg(ap, intmax_t); \ + break; \ + case 't': \ + val = va_arg(ap, ptrdiff_t); \ + break; \ + case 'z': \ + val = va_arg(ap, ssize_t); \ + break; \ + case 'z' | 0x80: \ + val = va_arg(ap, size_t); \ + break; \ + case 'p': /* Synthetic; used for %p. */ \ + val = va_arg(ap, uintptr_t); \ + break; \ + default: not_reached(); \ + } \ +} while (0) + + i = 0; + f = format; + while (true) { + switch (*f) { + case '\0': goto label_out; + case '%': { + bool alt_form = false; + bool left_justify = false; + bool plus_space = false; + bool plus_plus = false; + int prec = -1; + int width = -1; + unsigned char len = '?'; + + f++; + if (*f == '%') { + /* %% */ + APPEND_C(*f); + break; + } + /* Flags. */ + while (true) { + switch (*f) { + case '#': + assert(alt_form == false); + alt_form = true; + break; + case '-': + assert(left_justify == false); + left_justify = true; + break; + case ' ': + assert(plus_space == false); + plus_space = true; + break; + case '+': + assert(plus_plus == false); + plus_plus = true; + break; + default: goto label_width; + } + f++; + } + /* Width. */ + label_width: + switch (*f) { + case '*': + width = va_arg(ap, int); + f++; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + uintmax_t uwidth; + set_errno(0); + uwidth = malloc_strtoumax(f, (char **)&f, 10); + assert(uwidth != UINTMAX_MAX || get_errno() != + ERANGE); + width = (int)uwidth; + if (*f == '.') { + f++; + goto label_precision; + } else + goto label_length; + break; + } case '.': + f++; + goto label_precision; + default: goto label_length; + } + /* Precision. */ + label_precision: + switch (*f) { + case '*': + prec = va_arg(ap, int); + f++; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + uintmax_t uprec; + set_errno(0); + uprec = malloc_strtoumax(f, (char **)&f, 10); + assert(uprec != UINTMAX_MAX || get_errno() != + ERANGE); + prec = (int)uprec; + break; + } + default: break; + } + /* Length. */ + label_length: + switch (*f) { + case 'l': + f++; + if (*f == 'l') { + len = 'q'; + f++; + } else + len = 'l'; + break; + case 'j': + len = 'j'; + f++; + break; + case 't': + len = 't'; + f++; + break; + case 'z': + len = 'z'; + f++; + break; + default: break; + } + /* Conversion specifier. */ + switch (*f) { + char *s; + size_t slen; + case 'd': case 'i': { + intmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[D2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len); + s = d2s(val, (plus_plus ? '+' : (plus_space ? + ' ' : '-')), buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'o': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[O2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = o2s(val, alt_form, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'u': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[U2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = u2s(val, 10, false, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'x': case 'X': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[X2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = x2s(val, alt_form, *f == 'X', buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'c': { + unsigned char val; + char buf[2]; + + assert(len == '?' || len == 'l'); + assert_not_implemented(len != 'l'); + val = va_arg(ap, int); + buf[0] = val; + buf[1] = '\0'; + APPEND_PADDED_S(buf, 1, width, left_justify); + f++; + break; + } case 's': + assert(len == '?' || len == 'l'); + assert_not_implemented(len != 'l'); + s = va_arg(ap, char *); + slen = (prec == -1) ? strlen(s) : prec; + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + case 'p': { + uintmax_t val; + char buf[X2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, 'p'); + s = x2s(val, true, false, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } + default: not_implemented(); + } + break; + } default: { + APPEND_C(*f); + f++; + break; + }} + } + label_out: + if (i < size) + str[i] = '\0'; + else + str[size - 1] = '\0'; + ret = i; + +#undef APPEND_C +#undef APPEND_S +#undef APPEND_PADDED_S +#undef GET_ARG_NUMERIC + return (ret); +} + +JEMALLOC_ATTR(format(printf, 3, 4)) +int +malloc_snprintf(char *str, size_t size, const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = malloc_vsnprintf(str, size, format, ap); + va_end(ap); + + return (ret); +} + +void +malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, va_list ap) +{ + char buf[MALLOC_PRINTF_BUFSIZE]; + + if (write_cb == NULL) { + /* + * The caller did not provide an alternate write_cb callback + * function, so use the default one. malloc_write() is an + * inline function, so use malloc_message() directly here. + */ + write_cb = (je_malloc_message != NULL) ? je_malloc_message : + wrtmessage; + cbopaque = NULL; + } + + malloc_vsnprintf(buf, sizeof(buf), format, ap); + write_cb(cbopaque, buf); +} + +/* + * Print to a callback function in such a way as to (hopefully) avoid memory + * allocation. + */ +JEMALLOC_ATTR(format(printf, 3, 4)) +void +malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + malloc_vcprintf(write_cb, cbopaque, format, ap); + va_end(ap); +} + +/* Print to stderr in such a way as to avoid memory allocation. */ +JEMALLOC_ATTR(format(printf, 1, 2)) +void +malloc_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + malloc_vcprintf(NULL, NULL, format, ap); + va_end(ap); +} diff --git a/dep/jemalloc/src/zone.c b/dep/jemalloc/src/zone.c new file mode 100644 index 00000000000..c62c183f65e --- /dev/null +++ b/dep/jemalloc/src/zone.c @@ -0,0 +1,258 @@ +#include "jemalloc/internal/jemalloc_internal.h" +#ifndef JEMALLOC_ZONE +# error "This source file is for zones on Darwin (OS X)." +#endif + +/* + * The malloc_default_purgeable_zone function is only available on >= 10.6. + * We need to check whether it is present at runtime, thus the weak_import. + */ +extern malloc_zone_t *malloc_default_purgeable_zone(void) +JEMALLOC_ATTR(weak_import); + +/******************************************************************************/ +/* Data. */ + +static malloc_zone_t zone; +static struct malloc_introspection_t zone_introspect; + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static size_t zone_size(malloc_zone_t *zone, void *ptr); +static void *zone_malloc(malloc_zone_t *zone, size_t size); +static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); +static void *zone_valloc(malloc_zone_t *zone, size_t size); +static void zone_free(malloc_zone_t *zone, void *ptr); +static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size); +#if (JEMALLOC_ZONE_VERSION >= 5) +static void *zone_memalign(malloc_zone_t *zone, size_t alignment, +#endif +#if (JEMALLOC_ZONE_VERSION >= 6) + size_t size); +static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, + size_t size); +#endif +static void *zone_destroy(malloc_zone_t *zone); +static size_t zone_good_size(malloc_zone_t *zone, size_t size); +static void zone_force_lock(malloc_zone_t *zone); +static void zone_force_unlock(malloc_zone_t *zone); + +/******************************************************************************/ +/* + * Functions. + */ + +static size_t +zone_size(malloc_zone_t *zone, void *ptr) +{ + + /* + * There appear to be places within Darwin (such as setenv(3)) that + * cause calls to this function with pointers that *no* zone owns. If + * we knew that all pointers were owned by *some* zone, we could split + * our zone into two parts, and use one as the default allocator and + * the other as the default deallocator/reallocator. Since that will + * not work in practice, we must check all pointers to assure that they + * reside within a mapped chunk before determining size. + */ + return (ivsalloc(ptr, config_prof)); +} + +static void * +zone_malloc(malloc_zone_t *zone, size_t size) +{ + + return (je_malloc(size)); +} + +static void * +zone_calloc(malloc_zone_t *zone, size_t num, size_t size) +{ + + return (je_calloc(num, size)); +} + +static void * +zone_valloc(malloc_zone_t *zone, size_t size) +{ + void *ret = NULL; /* Assignment avoids useless compiler warning. */ + + je_posix_memalign(&ret, PAGE, size); + + return (ret); +} + +static void +zone_free(malloc_zone_t *zone, void *ptr) +{ + + if (ivsalloc(ptr, config_prof) != 0) { + je_free(ptr); + return; + } + + free(ptr); +} + +static void * +zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) +{ + + if (ivsalloc(ptr, config_prof) != 0) + return (je_realloc(ptr, size)); + + return (realloc(ptr, size)); +} + +#if (JEMALLOC_ZONE_VERSION >= 5) +static void * +zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) +{ + void *ret = NULL; /* Assignment avoids useless compiler warning. */ + + je_posix_memalign(&ret, alignment, size); + + return (ret); +} +#endif + +#if (JEMALLOC_ZONE_VERSION >= 6) +static void +zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) +{ + + if (ivsalloc(ptr, config_prof) != 0) { + assert(ivsalloc(ptr, config_prof) == size); + je_free(ptr); + return; + } + + free(ptr); +} +#endif + +static void * +zone_destroy(malloc_zone_t *zone) +{ + + /* This function should never be called. */ + assert(false); + return (NULL); +} + +static size_t +zone_good_size(malloc_zone_t *zone, size_t size) +{ + + if (size == 0) + size = 1; + return (s2u(size)); +} + +static void +zone_force_lock(malloc_zone_t *zone) +{ + + if (isthreaded) + jemalloc_prefork(); +} + +static void +zone_force_unlock(malloc_zone_t *zone) +{ + + if (isthreaded) + jemalloc_postfork_parent(); +} + +JEMALLOC_ATTR(constructor) +void +register_zone(void) +{ + + /* + * If something else replaced the system default zone allocator, don't + * register jemalloc's. + */ + malloc_zone_t *default_zone = malloc_default_zone(); + if (!default_zone->zone_name || + strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) { + return; + } + + zone.size = (void *)zone_size; + zone.malloc = (void *)zone_malloc; + zone.calloc = (void *)zone_calloc; + zone.valloc = (void *)zone_valloc; + zone.free = (void *)zone_free; + zone.realloc = (void *)zone_realloc; + zone.destroy = (void *)zone_destroy; + zone.zone_name = "jemalloc_zone"; + zone.batch_malloc = NULL; + zone.batch_free = NULL; + zone.introspect = &zone_introspect; + zone.version = JEMALLOC_ZONE_VERSION; +#if (JEMALLOC_ZONE_VERSION >= 5) + zone.memalign = zone_memalign; +#endif +#if (JEMALLOC_ZONE_VERSION >= 6) + zone.free_definite_size = zone_free_definite_size; +#endif +#if (JEMALLOC_ZONE_VERSION >= 8) + zone.pressure_relief = NULL; +#endif + + zone_introspect.enumerator = NULL; + zone_introspect.good_size = (void *)zone_good_size; + zone_introspect.check = NULL; + zone_introspect.print = NULL; + zone_introspect.log = NULL; + zone_introspect.force_lock = (void *)zone_force_lock; + zone_introspect.force_unlock = (void *)zone_force_unlock; + zone_introspect.statistics = NULL; +#if (JEMALLOC_ZONE_VERSION >= 6) + zone_introspect.zone_locked = NULL; +#endif +#if (JEMALLOC_ZONE_VERSION >= 7) + zone_introspect.enable_discharge_checking = NULL; + zone_introspect.disable_discharge_checking = NULL; + zone_introspect.discharge = NULL; +#ifdef __BLOCKS__ + zone_introspect.enumerate_discharged_pointers = NULL; +#else + zone_introspect.enumerate_unavailable_without_blocks = NULL; +#endif +#endif + + /* + * The default purgeable zone is created lazily by OSX's libc. It uses + * the default zone when it is created for "small" allocations + * (< 15 KiB), but assumes the default zone is a scalable_zone. This + * obviously fails when the default zone is the jemalloc zone, so + * malloc_default_purgeable_zone is called beforehand so that the + * default purgeable zone is created when the default zone is still + * a scalable_zone. As purgeable zones only exist on >= 10.6, we need + * to check for the existence of malloc_default_purgeable_zone() at + * run time. + */ + if (malloc_default_purgeable_zone != NULL) + malloc_default_purgeable_zone(); + + /* Register the custom zone. At this point it won't be the default. */ + malloc_zone_register(&zone); + + /* + * Unregister and reregister the default zone. On OSX >= 10.6, + * unregistering takes the last registered zone and places it at the + * location of the specified zone. Unregistering the default zone thus + * makes the last registered one the default. On OSX < 10.6, + * unregistering shifts all registered zones. The first registered zone + * then becomes the default. + */ + do { + default_zone = malloc_default_zone(); + malloc_zone_unregister(default_zone); + malloc_zone_register(default_zone); + } while (malloc_default_zone() != &zone); +} diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 4c4df0cdfb1..daa4e905970 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -34,6 +34,7 @@ CREATE TABLE `account` ( `last_ip` varchar(15) NOT NULL DEFAULT '127.0.0.1', `failed_logins` int(10) unsigned NOT NULL DEFAULT '0', `locked` tinyint(3) unsigned NOT NULL DEFAULT '0', + `lock_country` varchar(2) NOT NULL DEFAULT '00', `last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `online` tinyint(3) unsigned NOT NULL DEFAULT '0', `expansion` tinyint(3) unsigned NOT NULL DEFAULT '3', @@ -125,6 +126,32 @@ CREATE TABLE `ip_banned` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Banned IPs'; /*!40101 SET character_set_client = @saved_cs_client */; +/*Table structure for table `ip2nation` */ + +DROP TABLE IF EXISTS `ip2nation`; + +CREATE TABLE `ip2nation` ( + `ip` int(11) unsigned NOT NULL DEFAULT '0', + `country` char(2) NOT NULL DEFAULT '', + KEY `ip` (`ip`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*Table structure for table `ip2nationCountries` */ + +DROP TABLE IF EXISTS `ip2nationCountries`; + +CREATE TABLE `ip2nationCountries` ( + `code` varchar(4) NOT NULL DEFAULT '', + `iso_code_2` varchar(2) NOT NULL DEFAULT '', + `iso_code_3` varchar(3) DEFAULT '', + `iso_country` varchar(255) NOT NULL DEFAULT '', + `country` varchar(255) NOT NULL DEFAULT '', + `lat` float NOT NULL DEFAULT '0', + `lon` float NOT NULL DEFAULT '0', + PRIMARY KEY (`code`), + KEY `code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- -- Dumping data for table `ip_banned` -- diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index e5df0656417..4f698c10288 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -214,6 +214,32 @@ LOCK TABLES `auctionhouse` WRITE; UNLOCK TABLES; -- +-- Table structure for table `banned_addons` +-- + +DROP TABLE IF EXISTS `banned_addons`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `banned_addons` ( + `Id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `Name` varchar(255) NOT NULL, + `Version` varchar(255) NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Id`), + UNIQUE KEY `idx_name_ver` (`Name`, `Version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `banned_addons` +-- + +LOCK TABLES `banned_addons` WRITE; +/*!40000 ALTER TABLE `banned_addons` DISABLE KEYS */; +/*!40000 ALTER TABLE `banned_addons` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `bugreport` -- diff --git a/sql/updates/auth/2013_04_22_00_auth_misc.sql b/sql/updates/auth/2013_04_22_00_auth_misc.sql new file mode 100644 index 00000000000..508c0aab944 --- /dev/null +++ b/sql/updates/auth/2013_04_22_00_auth_misc.sql @@ -0,0 +1,21 @@ +ALTER TABLE `account` ADD COLUMN `lock_country` VARCHAR(2) NOT NULL DEFAULT '00' AFTER `locked`; + +DROP TABLE IF EXISTS ip2nation; +CREATE TABLE ip2nation ( + ip int(11) unsigned NOT NULL default '0', + country char(2) NOT NULL default '', + KEY ip (ip) +); + +DROP TABLE IF EXISTS ip2nationCountries; +CREATE TABLE ip2nationCountries ( + code varchar(4) NOT NULL default '', + iso_code_2 varchar(2) NOT NULL default '', + iso_code_3 varchar(3) default '', + iso_country varchar(255) NOT NULL default '', + country varchar(255) NOT NULL default '', + lat float NOT NULL default '0', + lon float NOT NULL default '0', + PRIMARY KEY (code), + KEY code (code) +); diff --git a/sql/updates/auth/2013_04_27_00_auth_misc.sql b/sql/updates/auth/2013_04_27_00_auth_misc.sql new file mode 100644 index 00000000000..383b19ebd55 --- /dev/null +++ b/sql/updates/auth/2013_04_27_00_auth_misc.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `autobroadcast`; +CREATE TABLE `autobroadcast` ( + `realmid` int(10) NOT NULL, + `id` int(11) NOT NULL AUTO_INCREMENT, + `weight` tinyint(3) DEFAULT 1, + `text` longtext NOT NULL, + PRIMARY KEY (`id`, `realmid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/characters/2013_04_05_00_characters_banned_addons.sql b/sql/updates/characters/2013_04_05_00_characters_banned_addons.sql new file mode 100644 index 00000000000..4f286b2326c --- /dev/null +++ b/sql/updates/characters/2013_04_05_00_characters_banned_addons.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `banned_addons`; +CREATE TABLE `banned_addons` ( + `Id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `Name` varchar(255) NOT NULL, + `Version` varchar(255) NOT NULL DEFAULT '', + `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Id`), + UNIQUE KEY `idx_name_ver` (`Name`, `Version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/world/2013_03_13_02_sai.sql b/sql/updates/world/2013_03_13_02_world_sai.sql index b3712d52197..70709b0ffcd 100644 --- a/sql/updates/world/2013_03_13_02_sai.sql +++ b/sql/updates/world/2013_03_13_02_world_sai.sql @@ -41,9 +41,3 @@ UPDATE `smart_scripts` SET `event_type`=0 WHERE `entryorguid`=83600 AND `source UPDATE `smart_scripts` SET `event_type`=0 WHERE `entryorguid`=83600 AND `source_type`=9 AND `id`=3 AND `link`=0; UPDATE `smart_scripts` SET `link`=0, `event_type`=0 WHERE `entryorguid`=305400 AND `source_type`=9 AND `id`=1 AND `link`=2; UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=15938 AND `source_type`=0 AND `id`=7 AND `link`=8; --- This one had messed up ID's too -UPDATE `smart_scripts` SET `id`=5, `link`=6 WHERE `entryorguid`=19456 AND `source_type`=0 AND `id`=6 AND `link`=7; -UPDATE `smart_scripts` SET `id`=6 WHERE `entryorguid`=19456 AND `source_type`=0 AND `id`=7 AND `link`=0; -UPDATE `smart_scripts` SET `id`=7 WHERE `entryorguid`=19456 AND `source_type`=0 AND `id`=8 AND `link`=0; -UPDATE `smart_scripts` SET `id`=8 WHERE `entryorguid`=19456 AND `source_type`=0 AND `id`=9 AND `link`=0; -UPDATE `smart_scripts` SET `id`=9 WHERE `entryorguid`=19456 AND `source_type`=0 AND `id`=10 AND `link`=0; diff --git a/sql/updates/world/2013_03_20_00_world_guardians_of_the_altar.sql b/sql/updates/world/2013_03_20_00_world_guardians_of_the_altar.sql index e1cfb8a2ac0..ce15a034185 100644 --- a/sql/updates/world/2013_03_20_00_world_guardians_of_the_altar.sql +++ b/sql/updates/world/2013_03_20_00_world_guardians_of_the_altar.sql @@ -115,6 +115,6 @@ INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x` (@GO_GUID+6,@GO_ELUNE_GEM,1,1,1,5514.49,-4917.57,850.538,2.3911,0,0,0.930417,0.366502,-900,100,1); -- EFFECT1 for 18953 -DELETE FROM `spell_dbc` WHERE `Id`=18954; -INSERT INTO `spell_dbc` (`Id`, `School`, `Category`, `CastUI`, `Dispel`, `Mechanic`, `Attributes`, `AttributesEx`, `AttributesEx2`, `AttributesEx3`, `AttributesEx4`, `Stances`, `StancesNot`, `Targets`, `TargetCreatureType`, `RequiresSpellFocus`, `CasterAuraState`, `TargetAuraState`, `CastingTimeIndex`, `RecoveryTime`, `CategoryRecoveryTime`, `InterruptFlags`, `AuraInterruptFlags`, `ChannelInterruptFlags`, `ProcFlags`, `ProcChance`, `ProcCharges`, `MaxLevel`, `BaseLevel`, `SpellLevel`, `DurationIndex`, `PowerType`, `PowerCost`, `PowerCostPerLevel`, `PowerCostPerSecond`, `PowerCostPerSecondPerLevel`, `RangeIndex`, `Speed`, `ModelNextSpell`, `StackAmount`, `Totem1`, `Totem2`, `Reagent1`, `Reagent2`, `Reagent3`, `Reagent4`, `Reagent5`, `Reagent6`, `Reagent7`, `Reagent8`, `ReagentCount1`, `ReagentCount2`, `ReagentCount3`, `ReagentCount4`, `ReagentCount5`, `ReagentCount6`, `ReagentCount7`, `ReagentCount8`, `EquippedItemClass`, `EquippedItemSubClassMask`, `EquippedItemInventoryTypeMask`, `Effect1`, `Effect2`, `Effect3`, `EffectDieSides1`, `EffectDieSides2`, `EffectDieSides3`, `EffectBaseDice1`, `EffectBaseDice2`, `EffectBaseDice3`, `EffectDicePerLevel1`, `EffectDicePerLevel2`, `EffectDicePerLevel3`, `EffectRealPointsPerLevel1`, `EffectRealPointsPerLevel2`, `EffectRealPointsPerLevel3`, `EffectBasePoints1`, `EffectBasePoints2`, `EffectBasePoints3`, `EffectMechanic1`, `EffectMechanic2`, `EffectMechanic3`, `EffectImplicitTargetA1`, `EffectImplicitTargetA2`, `EffectImplicitTargetA3`, `EffectImplicitTargetB1`, `EffectImplicitTargetB2`, `EffectImplicitTargetB3`, `EffectRadiusIndex1`, `EffectRadiusIndex2`, `EffectRadiusIndex3`, `EffectApplyAuraName1`, `EffectApplyAuraName2`, `EffectApplyAuraName3`, `EffectAmplitude1`, `EffectAmplitude2`, `EffectAmplitude3`, `EffectMultipleValue1`, `EffectMultipleValue2`, `EffectMultipleValue3`, `EffectChainTarget1`, `EffectChainTarget2`, `EffectChainTarget3`, `EffectItemType1`, `EffectItemType2`, `EffectItemType3`, `EffectMiscValue1`, `EffectMiscValue2`, `EffectMiscValue3`, `EffectTriggerSpell1`, `EffectTriggerSpell2`, `EffectTriggerSpell3`, `EffectPointsPerComboPoint1`, `EffectPointsPerComboPoint2`, `EffectPointsPerComboPoint3`, `SpellVisual`, `SpellVisual2`, `SpellIconID`, `ActiveIconID`, `SpellPriority`, `SpellName`, `Rank`, `Description`, `ToolTip`, `ManaCostPercentage`, `StartRecoveryCategory`, `StartRecoveryTime`, `MaxTargetLevel`, `SpellFamilyName`, `SpellFamilyFlags1`, `SpellFamilyFlags2`, `MaxAffectedTargets`, `DmgClass`, `PreventionType`, `StanceBarOrder`, `DmgMultiplier1`, `DmgMultiplier2`, `DmgMultiplier3`, `MinFactionId`, `MinReputation`, `RequiredAuraVision`) VALUES -(18954, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 'Ranshalla Despawn', '', '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0); +DELETE FROM `spell_dbc` WHERE `id`=18954; +INSERT INTO `spell_dbc` (`id`, `Attributes`, `CastingTimeIndex`, `ProcChance`, `RangeIndex`, `EquippedItemClass`, `Effect1`, `EffectImplicitTargetA1`, `DmgMultiplier1`, `Comment`) VALUES +(18954, 256, 1, 101, 1, -1, 3, 1, 1, 'Ranshalla Despawn'); diff --git a/sql/updates/world/2013_03_27_00_world_spell_target_position.sql b/sql/updates/world/2013_03_27_00_world_spell_target_position.sql new file mode 100644 index 00000000000..4991fb35aa8 --- /dev/null +++ b/sql/updates/world/2013_03_27_00_world_spell_target_position.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_target_position` WHERE `id`=71436; +INSERT INTO `spell_target_position`(`id`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation`) VALUE +(71436,-14459.48,492.46,15.12,3.21); diff --git a/sql/updates/world/2013_03_28_00_world_misc.sql b/sql/updates/world/2013_03_28_00_world_misc.sql new file mode 100644 index 00000000000..78e420872ba --- /dev/null +++ b/sql/updates/world/2013_03_28_00_world_misc.sql @@ -0,0 +1,12 @@ +SET @GOSSIP := 5750; +SET @LOTHOS := 14387; + +UPDATE `gossip_menu_option` SET `option_id`=1, `npc_option_npcflag`=1 WHERE `menu_id`=@GOSSIP; -- 4.3.4 (they are 0) + +DELETE FROM `smart_scripts` WHERE `entryorguid`=@LOTHOS AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@LOTHOS, 0, 0, 0, 62, 0, 100, 0, @GOSSIP, 0, 0, 0, 11, 25139, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Lothos Riftwaker - On Gossip select - Teleport player'); + +DELETE FROM `spell_target_position` WHERE `id`=25139; +INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES +(25139, 409, 1080, -483, -108, 1); -- Teleport to Molten Core DND diff --git a/sql/updates/world/2013_03_29_00_world_misc.sql b/sql/updates/world/2013_03_29_00_world_misc.sql new file mode 100644 index 00000000000..1a7e88b3d59 --- /dev/null +++ b/sql/updates/world/2013_03_29_00_world_misc.sql @@ -0,0 +1,240 @@ +SET @GUID := 61994; + +SET @NPC_ELM_BUNNY := 23837; +SET @NPC_ELM_BUNNY_LARGE := 24110; +SET @NPC_ELM_BUNNY_LARGE_001 := 26298; +SET @NPC_AKALI := 28952; +SET @NPC_AKALI_SUBDUER := 28988; +SET @NPC_AKALI_PROPHET := 28996; + +DELETE FROM `creature_text` WHERE `entry` IN (@NPC_AKALI,@NPC_AKALI_PROPHET); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_AKALI,0,0,'I''M FREE, LITTLE DRAKKARI. TIME TO PAY FOR YOUR MANY TRESSPASSES!',14,0,100,33,0,771,'Akali'), +(@NPC_AKALI_PROPHET,0,0,'ENOUGH!',14,0,100,15,0,0,'Prophet of Akali'), +(@NPC_AKALI_PROPHET,1,0,'And now, Akali, my master will have your blood and I will take some of your power as well!',14,0,100,397,0,0,'Prophet of Akali'), +(@NPC_AKALI_PROPHET,2,0,'It is done. Run back to your masters. Run back to Har''koa. Tell her that I am coming!',14,0,100,14,0,0,'Prophet of Akali'); + +UPDATE `creature_model_info` SET `bounding_radius`=1.041666, `combat_reach`=4.5 WHERE `modelid`=25839; + +UPDATE `creature_template` SET `rank`=1, `unit_flags`=33536, `dmg_multiplier`=10 WHERE `entry`=@NPC_AKALI; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (@NPC_ELM_BUNNY_LARGE,@NPC_AKALI,@NPC_AKALI_SUBDUER); +UPDATE `creature_template` SET `inhabitType`=4 WHERE `entry` IN (@NPC_ELM_BUNNY_LARGE,@NPC_ELM_BUNNY_LARGE_001); +UPDATE `creature_template` SET `faction_A`=2069, `faction_H`=2069, `unit_flags`=33536, `AIName`='SmartAI' WHERE `entry`=@NPC_AKALI_PROPHET; + +UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `guid` IN (100333,100334,100335,100336); +UPDATE `creature` SET `modelid`=21999 WHERE `id`=@NPC_ELM_BUNNY_LARGE_001; +DELETE FROM `creature` WHERE `guid` IN (@GUID+0,@GUID+1,@GUID+2); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`MovementType`) VALUES +(@GUID+0,@NPC_ELM_BUNNY_LARGE_001,571,1,1,0,6863.839,-4503.26,443.1838,3.926991,300,0,0), +(@GUID+1,@NPC_ELM_BUNNY_LARGE_001,571,1,1,0,6862.341,-4549.724,443.0588,2.286381,300,0,0), +(@GUID+2,@NPC_ELM_BUNNY,571,1,1,11686,6829.338,-4525.157,442.068,3.420845,300,0,0); + +DELETE FROM `creature_addon` WHERE `guid` IN (100333,100334,100335,100336); +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(100333,0,0,0,1,0,'52855'), +(100334,0,0,0,1,0,'52855'), +(100335,0,0,0,1,0,'52855'), +(100336,0,0,0,1,0,'52855'); + +DELETE FROM `creature_summon_groups` WHERE `summonerId`=@NPC_AKALI; +INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6810.893,-4592.669,440.6777,1.299272,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6806.189,-4595.943,440.6777,1.250024,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6822.087,-4599.02,440.6777,1.469111,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6797.534,-4594.82,440.685,1.137566,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6827.478,-4601.454,440.6777,1.543024,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6817.193,-4601.688,440.6777,1.409492,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6834.823,-4602.401,440.6777,1.638796,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6805.295,-4601.961,440.6777,1.263096,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6765.525,-4543.851,440.6777,0.2786701,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6764.082,-4549.868,440.6777,0.3558455,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6765.489,-4564.422,440.6777,0.5454721,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6763.994,-4537.706,440.6782,0.1836674,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6826.999,-4607.5,440.6777,1.539239,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6763.607,-4558.375,440.6785,0.4619856,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6796.735,-4602.545,441.0136,1.167641,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6832.644,-4607.751,440.6777,1.607957,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6810.649,-4609.51,440.6977,1.349023,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6821.64,-4610.604,440.6777,1.477666,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6759.292,-4545.87,440.828,0.2817687,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6758.293,-4555.154,440.7154,0.393915,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6758.89,-4536.409,441.8029,0.152804,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6759.161,-4564.057,440.7889,0.5006734,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6800.313,-4611.478,442.0841,1.242545,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6755.442,-4540.723,441.9008,0.2022173,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6756.493,-4531.063,443.5255,0.07566226,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6754.277,-4551.221,440.8657,0.3288565,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6815.617,-4616.651,440.7146,1.418685,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6753.755,-4559.585,441.2291,0.4221908,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6750.038,-4544.226,441.7151,0.2309312,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6748.174,-4550.871,441.9503,0.301857,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6901.166,-4516.716,440.6777,3.263991,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6904.161,-4525.245,440.6777,3.145305,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6843.423,-4464.692,440.6777,4.488739,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6894.436,-4500.116,440.6777,3.514982,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6908.481,-4530.965,440.6777,3.0727,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6851.518,-4464.19,440.6777,4.368972,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6903.379,-4508.444,440.6777,3.369018,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6862.596,-4466.07,440.6777,4.205543,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6907.354,-4513.603,440.6777,3.293668,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6847.208,-4459.859,440.6799,4.450202,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6901.388,-4500.221,440.6777,3.480376,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6910.758,-4518.518,440.6777,3.22766,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6877.528,-4472.05,440.6777,3.981474,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6906.053,-4501.915,440.6777,3.441033,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6855.152,-4457.84,440.2045,4.351227,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6903.093,-4495.178,440.6777,3.533091,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6871.4,-4463.921,440.6777,4.11605,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6911.422,-4507.554,440.6777,3.357718,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6916.012,-4518.927,440.6807,3.217745,3,100000), +(@NPC_AKALI,0,1,@NPC_AKALI_SUBDUER,6864.756,-4459.202,440.6777,4.224802,3,100000); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (52816,52833,52834,52837,52838,52844,52867,52884); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,52816,0,0,31,0,3,@NPC_ELM_BUNNY_LARGE,0,0,0,'','Spell Akali Chain Anchor On Disturb targets ELM General Purpose Bunny Large'), +(13,1,52816,0,1,31,0,3,@NPC_ELM_BUNNY_LARGE_001,0,0,0,'','Spell Akali Chain Anchor On Disturb targets ELM General Purpose Bunny Large'), +(13,1,52833,0,0,31,0,3,@NPC_AKALI,0,0,0,'','Spell Akali''s Chains - Left Front Paw targets Akali'), +(13,1,52834,0,0,31,0,3,@NPC_AKALI,0,0,0,'','Spell Akali''s Chains - Right Front Paw targets Akali'), +(13,1,52837,0,0,31,0,3,@NPC_ELM_BUNNY_LARGE_001,0,0,0,'','Spell Akali''s Chains - Right Rear Paw targets ELM General Purpose Bunny Large'), +(13,1,52837,0,0,35,0,1,5,3,0,0,'','Spell Akali''s Chains - Right Rear Paw target distance must be 5y or more'), +(13,1,52838,0,0,31,0,3,@NPC_ELM_BUNNY_LARGE_001,0,0,0,'','Spell Akali''s Chains - Left Rear Paw targets ELM General Purpose Bunny Large'), +(13,1,52838,0,0,35,0,1,5,3,0,0,'','Spell Akali''s Chains - Left Rear Paw target distance must be 5y or more'), +(13,1,52844,0,0,31,0,3,@NPC_AKALI,0,0,0,'','Spell Akali''s Chains - Rear Paw Invisible Stun Channel targets Akali'), +(13,1,52867,0,0,31,0,3,@NPC_AKALI_SUBDUER,0,0,0,'','Spell Knockback targets Akali Subduer'), +(13,1,52884,0,0,31,0,3,@NPC_AKALI,0,0,0,'','Spell Drain Power targets Akali'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=52860; +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(52860,45254,1,'On spellhit Rampage: Drain Power Effect - Spellcast Suicide'); + +DELETE FROM `spell_dbc` WHERE `Id`=52867; +INSERT INTO `spell_dbc` (`Id`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`AttributesEx6`,`AttributesEx7`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectMiscValueB1`,`EffectMiscValueB2`,`EffectMiscValueB3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`EffectSpellClassMaskA1`,`EffectSpellClassMaskA2`,`EffectSpellClassMaskA3`,`EffectSpellClassMaskB1`,`EffectSpellClassMaskB2`,`EffectSpellClassMaskB3`,`EffectSpellClassMaskC1`,`EffectSpellClassMaskC2`,`EffectSpellClassMaskC3`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`SpellFamilyFlags3`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`AreaGroupId`,`SchoolMask`,`Comment`) VALUES +(52867,0,0,538968320,525448,67108868,64,2177,0,512,0,0,0,0,1,0,0,101,0,0,0,0,0,1,0,-1,0,0,98,0,0,1,0,0,0,0,0,199,0,0,0,0,0,22,0,0,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0,150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'Knockback'); + +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=28575; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-100333,-100334,-100335,-100336,-113548,-113549,-113550,-113551,-(@GUID+0),-(@GUID+1),-(@GUID+2),@NPC_AKALI,@NPC_AKALI_SUBDUER,@NPC_AKALI_PROPHET) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_AKALI*100+0,@NPC_AKALI*100+1,@NPC_AKALI_SUBDUER*100,@NPC_AKALI_PROPHET*100+0,@NPC_AKALI_PROPHET*100+1) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-100333,0,0,1,8,0,100,0,52816,0,0,0,45,0,1,0,0,0,0,10,@GUID+2,@NPC_ELM_BUNNY,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Set data 0 1 ELM General Purpose Bunny'), +(-100333,0,1,0,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-100334,0,0,1,8,0,100,0,52816,0,0,0,45,0,1,0,0,0,0,10,@GUID+2,@NPC_ELM_BUNNY,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Set data 0 1 ELM General Purpose Bunny'), +(-100334,0,1,0,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-100335,0,0,1,8,0,100,0,52816,0,0,0,45,0,1,0,0,0,0,10,@GUID+2,@NPC_ELM_BUNNY,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Set data 0 1 ELM General Purpose Bunny'), +(-100335,0,1,0,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-100336,0,0,1,8,0,100,0,52816,0,0,0,45,0,1,0,0,0,0,10,@GUID+2,@NPC_ELM_BUNNY,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Set data 0 1 ELM General Purpose Bunny'), +(-100336,0,1,0,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), + +(-113548,0,0,0,38,0,100,0,0,1,0,0,11,52833,0,0,0,0,0,10,98159,@NPC_AKALI,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Akali''s Chains - Left Front Paw'), +(-113548,0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-113549,0,0,0,38,0,100,0,0,1,0,0,11,52834,0,0,0,0,0,10,98159,@NPC_AKALI,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Akali''s Chains - Right Front Paw'), +(-113549,0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-113550,0,0,0,38,0,100,0,0,1,0,0,11,52844,0,0,0,0,0,10,98159,@NPC_AKALI,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Rear Paw Invisible Stun Channel'), +(-113550,0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-113551,0,0,0,38,0,100,0,0,1,0,0,11,52844,0,0,0,0,0,10,98159,@NPC_AKALI,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Rear Paw Invisible Stun Channel'), +(-113551,0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-(@GUID+0),0,0,0,38,0,100,0,0,1,0,0,11,52837,0,0,0,0,0,10,113478,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Akali''s Chains - Right Rear Paw'), +(-(@GUID+0),0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), +(-(@GUID+1),0,0,0,38,0,100,0,0,1,0,0,11,52838,0,0,0,0,0,10,113479,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Spellcast Akali''s Chains - Left Rear Paw'), +(-(@GUID+1),0,1,0,8,0,100,0,52816,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Chain Anchor On Disturb - Despawn'), + +(-(@GUID+2),0,0,1,1,8,100,0,0,0,500,500,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC (phase 4) - Set event phase 0'), +(-(@GUID+2),0,1,0,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,19,@NPC_AKALI,30,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC (phase 4) - Set data 0 1 Akali'), +(-(@GUID+2),0,2,0,38,0,100,0,0,1,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On data 0 1 set - Increment event phase'), + +(@NPC_AKALI,0,0,0,38,0,100,0,0,1,0,0,80,@NPC_AKALI*100+0,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali - On data 0 1 set - Run script 0'), +(@NPC_AKALI,0,1,2,8,0,100,0,52859,0,0,0,102,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali - On spellhit Submission - Stop regen health'), +(@NPC_AKALI,0,2,3,61,0,100,0,0,0,0,0,18,512,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali - On spellhit Submission - Set unit_flags IMMUNE_TO_NPC'), +(@NPC_AKALI,0,3,0,61,0,100,0,0,0,0,0,69,1,0,0,0,0,0,8,0,0,0,6829.587,-4525.521,442.068,0, 'Akali - On spellhit Submission - Move to position'), +(@NPC_AKALI,0,4,0,34,0,100,0,0,1,0,0,80,@NPC_AKALI*100+1,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali - On movement inform - Run script 1'), +(@NPC_AKALI,0,5,0,9,0,100,0,0,80,10000,10000,11,52856,0,0,0,0,0,6,0,0,0,0,0,0,0, 'Akali - On target range 10-80y - Spellcast Charge'), +(@NPC_AKALI,0,6,7,11,0,100,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali - On spawn - Set faction default'), +(@NPC_AKALI,0,7,8,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,113548,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,8,9,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,113549,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,9,10,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,113550,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,10,11,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,113551,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,11,12,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,@GUID+0,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,12,13,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,@GUID+1,@NPC_ELM_BUNNY_LARGE_001,0,0,0,0,0, 'Akali - On spawn - Set data 0 1 ELM General Purpose Bunny'), +(@NPC_AKALI,0,13,14,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101661,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,14,15,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101662,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,15,16,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101663,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,16,17,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101665,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,17,18,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101666,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,18,19,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101667,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,19,20,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101668,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,20,21,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,101669,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,21,22,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203572,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,22,23,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203573,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,23,24,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203574,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,24,25,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203575,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,25,26,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203576,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), +(@NPC_AKALI,0,26,0,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,203577,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script - On spawn - Set data 0 1 Akali Subduer'), + +(@NPC_AKALI_SUBDUER,0,0,0,2,0,100,0,0,50,90000,90000,11,57843,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On health below 50% - Spellcast Mojo Empowered Fire Ward'), +(@NPC_AKALI_SUBDUER,0,1,0,9,0,100,0,25,35,4000,7000,11,9053,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Akali Subduer - On target range 0-35y - Spellcast Fireball'), +(@NPC_AKALI_SUBDUER,0,2,0,9,0,100,0,0,25,3000,5000,11,20801,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Akali Subduer - On target range 0-35y - Spellcast Firebolt'), +(@NPC_AKALI_SUBDUER,0,3,4,54,0,100,0,0,0,0,0,2,2102,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - Just summoned - Set faction'), +(@NPC_AKALI_SUBDUER,0,4,5,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - Just summoned - Set unit_flags IMMUNE_TO_PC'), +(@NPC_AKALI_SUBDUER,0,5,6,61,0,100,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - Just summoned - Set run'), +(@NPC_AKALI_SUBDUER,0,6,0,61,0,100,0,0,0,0,0,46,60,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - Just summoned - Move forward'), +(@NPC_AKALI_SUBDUER,0,7,8,31,0,100,0,52859,0,0,0,101,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On target spellhit Submission - Set homeposition'), +(@NPC_AKALI_SUBDUER,0,8,0,61,0,100,0,0,0,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On target spellhit Submission - Evade'), +(@NPC_AKALI_SUBDUER,0,9,10,38,0,100,0,0,3,0,0,92,0,0,1,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 3 set - Interrupt spellcast'), +(@NPC_AKALI_SUBDUER,0,10,0,61,0,100,0,0,0,0,0,20,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 3 set - Stop combat'), +(@NPC_AKALI_SUBDUER,0,11,0,38,0,100,0,0,1,0,0,11,45579,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 1 set - Spellcast Fire Channeling'), +(@NPC_AKALI_SUBDUER,0,12,13,38,0,100,0,0,2,0,0,2,2102,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 2 set - Set faction'), +(@NPC_AKALI_SUBDUER,0,13,0,61,0,100,0,0,0,0,0,92,0,45579,1,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 2 set - Interrupt spellcast'), +(@NPC_AKALI_SUBDUER,0,14,0,38,0,100,0,0,4,0,0,80,@NPC_AKALI_SUBDUER*100,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer - On data 0 4 set - Run script'), + +(@NPC_AKALI_PROPHET,0,0,1,54,0,100,0,0,0,0,0,11,34427,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali - Just summoned - Spellcast Ethereal Teleport'), +(@NPC_AKALI_PROPHET,0,1,0,61,0,100,0,0,0,0,0,1,0,2300,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali - Just summoned - Say line'), +(@NPC_AKALI_PROPHET,0,2,3,52,0,100,0,0,@NPC_AKALI_PROPHET,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali - On text over - Set run'), +(@NPC_AKALI_PROPHET,0,3,0,61,0,100,0,0,0,0,0,69,1,0,0,0,0,0,8,0,0,0,6869.146,-4558.086,443.3982,0, 'Prophet of Akali - On text over - Move to position'), +(@NPC_AKALI_PROPHET,0,4,5,34,0,100,0,0,1,0,0,97,30.7787,0,0,0,0,0,1,0,0,0,6856.265,-4543.67,441.9847,0, 'Prophet of Akali - On movement inform - Jump to position'), +(@NPC_AKALI_PROPHET,0,5,0,61,0,100,0,0,0,0,0,80,@NPC_AKALI_PROPHET*100+0,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali - On WP 1 reached - Run script 0'), +(@NPC_AKALI_PROPHET,0,6,0,38,0,100,0,0,1,0,0,80,@NPC_AKALI_PROPHET*100+1,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali - On data 0 1 set - Run script 1'), + +(@NPC_AKALI*100,9,0,0,0,0,100,0,2000,2000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali script 0 - Say line'), +(@NPC_AKALI*100,9,1,0,0,0,100,0,0,0,0,0,15,12721,0,0,0,0,0,18,50,0,0,0,0,0,0, 'Akali script 0 - Quest credit'), +(@NPC_AKALI*100,9,2,0,0,0,100,0,0,0,0,0,107,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 'Akali script 0 - Summon creature group'), +(@NPC_AKALI*100,9,3,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101661,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,4,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101662,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,5,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101663,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,6,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101665,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,7,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101666,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,8,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101667,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,9,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101668,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,10,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,101669,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,11,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203572,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,12,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203573,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,13,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203574,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,14,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203575,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,15,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203576,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,16,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,10,203577,@NPC_AKALI_SUBDUER,0,0,0,0,0, 'Akali script 0 - Set data 0 2 Akali Subduer'), +(@NPC_AKALI*100,9,17,0,0,0,100,0,4600,4600,0,0,19,512,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali script - Remove unit_flags IMMUNE_TO_NPC'), +(@NPC_AKALI*100,9,18,0,0,0,100,0,55000,55000,0,0,12,@NPC_AKALI_PROPHET,8,0,0,0,0,8,0,0,0,6882.029,-4571.001,442.3118,2.373648, 'Akali script - Summon Akali Prophet'), + +(@NPC_AKALI*100+1,9,0,0,0,0,100,0,0,0,0,0,2,35,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali script 1 - Set faction'), +(@NPC_AKALI*100+1,9,1,0,0,0,100,0,0,0,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali script 1 - Evade'), +(@NPC_AKALI*100+1,9,2,0,0,0,100,0,200,200,0,0,66,0,0,0,0,0,0,19,@NPC_AKALI_PROPHET,100,0,0,0,0,0, 'Akali script 1 - Turn to'), +(@NPC_AKALI*100+1,9,3,0,0,0,100,0,0,0,0,0,45,0,1,0,0,0,0,19,@NPC_AKALI_PROPHET,100,0,0,0,0,0, 'Akali script 1 - Set data 0 1 Prophet of Akali'), + +(@NPC_AKALI_SUBDUER*100,9,0,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,19,@NPC_AKALI_PROPHET,100,0,0,0,0,0, 'Akali Subduer script - Turn to'), +(@NPC_AKALI_SUBDUER*100,9,1,0,0,0,100,0,10000,10000,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,2,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,3,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,4,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,5,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,6,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,7,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,8,0,0,0,100,0,1000,1200,0,0,5,71,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Play emote'), +(@NPC_AKALI_SUBDUER*100,9,9,0,0,0,100,0,1000,1200,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akali Subduer script - Despawn'), + +(@NPC_AKALI_PROPHET*100+0,9,0,0,0,0,100,0,0,0,0,0,45,0,3,0,0,0,0,9,@NPC_AKALI_SUBDUER,0,100,0,0,0,0, 'Prophet of Akali script - Set data 0 4 Akali Subduer'), +(@NPC_AKALI_PROPHET*100+0,9,1,0,0,0,100,0,1000,1000,0,0,11,52859,0,0,0,0,0,19,@NPC_AKALI,100,0,0,0,0,0, 'Prophet of Akali script - Spellcast Submission'), + +(@NPC_AKALI_PROPHET*100+1,9,0,0,0,0,100,0,2000,2000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali script - Say line'), +(@NPC_AKALI_PROPHET*100+1,9,1,0,0,0,100,0,4700,4700,0,0,11,52884,0,0,0,0,0,19,@NPC_AKALI,50,0,0,0,0,0, 'Prophet of Akali script - Spellcast Drain Power'), +(@NPC_AKALI_PROPHET*100+1,9,2,0,0,0,100,0,0,0,0,0,45,0,4,0,0,0,0,9,@NPC_AKALI_SUBDUER,0,100,0,0,0,0, 'Prophet of Akali script - Set data 0 3 Akali Subduer'), +(@NPC_AKALI_PROPHET*100+1,9,3,0,0,0,100,0,11600,11600,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali script - Say line'), +(@NPC_AKALI_PROPHET*100+1,9,4,0,0,0,100,0,3500,3500,0,0,11,34427,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali script - Spellcast Ethereal Teleport'), +(@NPC_AKALI_PROPHET*100+1,9,5,0,0,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Prophet of Akali script - Despawn'); diff --git a/sql/updates/world/2013_03_29_01_world_misc.sql b/sql/updates/world/2013_03_29_01_world_misc.sql new file mode 100644 index 00000000000..bf59a7196c7 --- /dev/null +++ b/sql/updates/world/2013_03_29_01_world_misc.sql @@ -0,0 +1,87 @@ +SET @NPC_ELM_BUNNY := 23837; +SET @NPC_HARKOA := 28401; +SET @NPC_KHUFU := 28479; +SET @NPC_AKILZON := 29021; +SET @NPC_HALAZZI := 29022; +SET @NPC_JANALAI := 29023; +SET @NPC_NALORAKK := 29024; + +DELETE FROM `creature_text` WHERE `entry`=@NPC_HARKOA AND `groupid`=1; +DELETE FROM `creature_text` WHERE `entry` IN (@NPC_AKILZON,@NPC_HALAZZI,@NPC_JANALAI,@NPC_NALORAKK); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_HARKOA,1,0,'No, not Akali too!',15,0,100,0,0,0,'Har''koa'), +(@NPC_AKILZON,0,0,'And yet we see only doom in your future. It is your destiny that you do this, $N, but we fear that the prophet is too powerful for you and your friends. Still, you must try.',12,0,100,0,0,12196,'Akil''zon'), +(@NPC_HALAZZI,0,0,'Once more we hear your call, Khufu. We have wisdom for you and $N. You face great peril and must act swiftly or you all and Har''koa will die.',12,0,100,0,0,643,'Halazzi'), +(@NPC_JANALAI,0,0,'The gusty essence of deceased Quetz''lun''s wardens must be gathered to draw him near. To Har''koa must both of these rarities be delivered.',12,0,100,0,0,9919,'Jana''lai'), +(@NPC_NALORAKK,0,0,'The unblemished heart of the guardian must be secured to show defiance and strength. Jealous Zim''Rhuk keeps those who harbor it.',12,0,100,0,0,473,'Nalorakk'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (52934,52935,52936,52937); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,52934,0,0,31,0,3,@NPC_ELM_BUNNY,0,0,0,'','Spell Rampage: Summon Akil''zon targets ELM General Purpose Bunny'), +(13,1,52934,0,0,29,0,28527,10,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 35y from Chronicler To''kini'), +(13,1,52934,0,0,29,0,28527,15,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 35y from Chronicler To''kini'), +(13,1,52934,0,0,29,0,28527,30,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 35y from Chronicler To''kini'), +(13,1,52934,0,0,29,0,28527,35,0,0,0,'','Spell Rampage: Summon Akil''zon target needs to be 35y from Chronicler To''kini'), +(13,1,52935,0,0,31,0,3,@NPC_ELM_BUNNY,0,0,0,'','Spell Rampage: Summon Akil''zon targets ELM General Purpose Bunny'), +(13,1,52935,0,0,29,0,28527,10,0,0,0,'','Spell Rampage: Summon Akil''zon target needs to be 10y from Chronicler To''kini'), +(13,1,52936,0,0,31,0,3,@NPC_ELM_BUNNY,0,0,0,'','Spell Rampage: Summon Akil''zon targets ELM General Purpose Bunny'), +(13,1,52936,0,0,29,0,28527,10,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 15y from Chronicler To''kini'), +(13,1,52936,0,0,29,0,28527,15,0,0,0,'','Spell Rampage: Summon Akil''zon target needs to be 15y from Chronicler To''kini'), +(13,1,52937,0,0,31,0,3,@NPC_ELM_BUNNY,0,0,0,'','Spell Rampage: Summon Akil''zon targets ELM General Purpose Bunny'), +(13,1,52937,0,0,29,0,28527,10,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 30y from Chronicler To''kini'), +(13,1,52937,0,0,29,0,28527,15,0,1,0,'','Spell Rampage: Summon Akil''zon target needs to be 30y from Chronicler To''kini'), +(13,1,52937,0,0,29,0,28527,30,0,0,0,'','Spell Rampage: Summon Akil''zon target needs to be 30y from Chronicler To''kini'); + +DELETE FROM `spell_scripts` WHERE `id`=52933; +INSERT INTO `spell_scripts` (`id`,`effIndex`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`) VALUES +(52933,0,0,15,52934,0,0,0,0,0,0), +(52933,0,0,15,52935,0,0,0,0,0,0), +(52933,0,0,15,52936,0,0,0,0,0,0), +(52933,0,0,15,52937,0,0,0,0,0,0); + +UPDATE `creature_model_info` SET `bounding_radius`=0.93 WHERE `modelid`=21793; +UPDATE `creature_model_info` SET `bounding_radius`=1.833, `combat_reach`=4.5 WHERE `modelid`=21830; +UPDATE `creature_model_info` SET `bounding_radius`=0.525, `combat_reach`=2.625 WHERE `modelid`=21831; +UPDATE `creature_model_info` SET `bounding_radius`=0.775, `combat_reach`=5 WHERE `modelid`=22256; + +DELETE FROM `creature_template_addon` WHERE `entry`=29021; +INSERT INTO `creature_template_addon` (`entry`,`bytes1`) VALUES +(29021,33554432); + +UPDATE `creature_template` SET `minlevel`=83, `maxlevel`=83, `faction_A`=1610, `faction_H`=1610, `unit_flags`=512|256, `AIName`='SmartAI' WHERE `entry` IN (@NPC_AKILZON,@NPC_HALAZZI,@NPC_JANALAI,@NPC_NALORAKK); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=@NPC_HARKOA AND `source_type`=0 AND `id`=16; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@NPC_KHUFU AND `source_type`=0 AND `id` IN (3,4,5); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_AKILZON,@NPC_HALAZZI,@NPC_JANALAI,@NPC_NALORAKK) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@NPC_HALAZZI*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_HARKOA,0,16,15,38,0,100,0,0,2,0,0,1,1,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Har''koa - On data 0 2 set - Say line'), + +(@NPC_KHUFU,0,3,4,20,0,100,0,12721,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Khufu - On quest rewarded - Store targetlist'), +(@NPC_KHUFU,0,4,5,61,0,100,0,0,0,0,0,100,1,0,0,0,0,0,19,@NPC_HARKOA,100,0,0,0,0,0, 'Khufu - On quest rewarded - Send targetlist to Har''koa'), +(@NPC_KHUFU,0,5,0,61,0,100,0,0,0,0,0,45,0,2,0,0,0,0,19,@NPC_HARKOA,100,0,0,0,0,0, 'Khufu - On quest rewarded - Set data 0 2 Har''koa'), + +(@NPC_AKILZON,0,0,0,54,0,100,0,0,0,0,0,11,35426,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akil''zon - Just summoned - Spellcast Arcane Explosion Visual'), +(@NPC_AKILZON,0,1,0,38,0,100,0,0,1,0,0,1,0,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Akil''zon - On data 0 1 set - Say line'), +(@NPC_AKILZON,0,2,0,38,0,100,0,0,2,0,0,41,800,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Akil''zon - On data 0 2 set - Despawn'), + +(@NPC_HALAZZI,0,0,1,54,0,100,0,0,0,0,0,11,35426,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Halazzi - Just summoned - Spellcast Arcane Explosion Visual'), +(@NPC_HALAZZI,0,1,0,61,0,100,0,0,0,0,0,80,@NPC_HALAZZI*100,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Halazzi - Just summoned - Run script'), + +(@NPC_JANALAI,0,0,0,54,0,100,0,0,0,0,0,11,35426,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jana''lai - Just summoned - Spellcast Arcane Explosion Visual'), +(@NPC_JANALAI,0,1,0,38,0,100,0,0,1,0,0,1,0,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Jana''lai - On data 0 1 set - Say line'), +(@NPC_JANALAI,0,2,0,38,0,100,0,0,2,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jana''lai - On data 0 2 set - Despawn'), + +(@NPC_NALORAKK,0,0,0,54,0,100,0,0,0,0,0,11,35426,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Nalorakk - Just summoned - Spellcast Arcane Explosion Visual'), +(@NPC_NALORAKK,0,1,0,38,0,100,0,0,1,0,0,1,0,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Nalorakk - On data 0 1 set - Say line'), +(@NPC_NALORAKK,0,2,0,38,0,100,0,0,2,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Nalorakk - On data 0 2 set - Despawn'), + +(@NPC_HALAZZI*100,9,0,0,0,0,100,0,3300,3300,0,0,1,0,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Halazzi script - Say line'), +(@NPC_HALAZZI*100,9,1,0,0,0,100,0,5200,5200,0,0,45,0,1,0,0,0,0,19,@NPC_NALORAKK,20,0,0,0,0,0, 'Halazzi script - Set data 0 1 Nalorakk'), +(@NPC_HALAZZI*100,9,2,0,0,0,100,0,5600,5600,0,0,45,0,1,0,0,0,0,19,@NPC_JANALAI,20,0,0,0,0,0, 'Halazzi script - Set data 0 1 Jana''lai'), +(@NPC_HALAZZI*100,9,3,0,0,0,100,0,7700,7700,0,0,45,0,1,0,0,0,0,19,@NPC_AKILZON,20,0,0,0,0,0, 'Halazzi script - Set data 0 1 Akil''zon'), +(@NPC_HALAZZI*100,9,4,0,0,0,100,0,8300,8300,0,0,45,0,2,0,0,0,0,19,@NPC_JANALAI,20,0,0,0,0,0, 'Halazzi script - Set data 0 2 Jana''lai'), +(@NPC_HALAZZI*100,9,5,0,0,0,100,0,800,800,0,0,11,42466,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Halazzi script - Spellcast Spirit Visual'), +(@NPC_HALAZZI*100,9,6,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,19,@NPC_AKILZON,20,0,0,0,0,0, 'Halazzi script - Set data 0 2 Akil''zon'), +(@NPC_HALAZZI*100,9,7,0,0,0,100,0,0,0,0,0,45,0,2,0,0,0,0,19,@NPC_NALORAKK,20,0,0,0,0,0, 'Halazzi script - Set data 0 2 Nalorakk'), +(@NPC_HALAZZI*100,9,8,0,0,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Halazzi script - Despawn'); diff --git a/sql/updates/world/2013_03_29_02_world_waypoint_data.sql b/sql/updates/world/2013_03_29_02_world_waypoint_data.sql new file mode 100644 index 00000000000..edee2e67b48 --- /dev/null +++ b/sql/updates/world/2013_03_29_02_world_waypoint_data.sql @@ -0,0 +1,127 @@ +DELETE FROM `creature_addon` WHERE `guid` BETWEEN 202441 AND 202460; +INSERT INTO `creature_addon`(`guid`,`path_id`,`bytes1`) VALUES +(202441,2024410,50331648), +(202442,2024410,50331648), +(202443,2024430,50331648), +(202444,2024430,50331648), +(202445,2024450,50331648), +(202446,2024410,50331648), +(202447,2024470,50331648), +(202448,2024450,50331648), +(202449,2024450,50331648), +(202450,2024450,50331648), +(202451,2024510,50331648), +(202452,2024520,50331648), +(202453,2024430,50331648), +(202454,2024430,50331648), +(202455,2024410,50331648), +(202456,2024450,50331648), +(202457,2024510,50331648), +(202458,2024510,50331648), +(202459,2024510,50331648), +(202460,2024430,50331648); + +DELETE FROM `waypoint_data` WHERE `id` IN (2024410,2024430,2024450,2024470,2024520,2024510); +INSERT INTO `waypoint_data`(`id`,`point`,`position_x`,`position_y`,`position_z`) VALUES +(2024410,1,7210.96,-1046.89,1006.18), +(2024410,2,6998.46,-1076.85,1024.82), +(2024410,3,6874.25,-1097.38,927.736), +(2024410,4,6614.79,-875.755,812.765), +(2024410,5,6563.27,-811.767,749.876), +(2024410,6,6299.5,-797.577,529.126), +(2024410,7,6194.55,-1013.14,501.542), +(2024410,8,6319.25,-1251.66,468.626), +(2024410,9,6309.16,-1537.86,615.042), +(2024410,10,6748.21,-1664.31,919.312), +(2024410,11,6913.31,-1725.26,954.792), +(2024410,12,7167.58,-1501.69,962.569), +(2024410,13,7440.4,-1295.86,997.291), +(2024410,14,7024.75,-1625.54,957.369), +(2024410,15,7025.49,-1624.87,957.369), +(2024410,16,7167.58,-1501.69,962.569), +(2024410,17,7440.4,-1295.86,997.291), +(2024430,1,7440.4,-1295.86,997.291), +(2024430,2,7210.96,-1046.89,1006.18), +(2024430,3,6998.46,-1076.85,1024.82), +(2024430,4,6874.25,-1097.38,927.736), +(2024430,5,6614.79,-875.755,812.765), +(2024430,6,6563.27,-811.767,749.876), +(2024430,7,6299.5,-797.577,529.126), +(2024430,8,6194.55,-1013.14,501.542), +(2024430,9,6319.25,-1251.66,468.626), +(2024430,10,6309.16,-1537.86,615.042), +(2024430,11,6748.21,-1664.31,919.312), +(2024430,12,6913.31,-1725.26,954.792), +(2024430,13,7167.58,-1501.69,962.569), +(2024430,14,7440.4,-1295.86,997.291), +(2024430,15,7024.75,-1625.54,957.369), +(2024430,16,7025.49,-1624.87,957.369), +(2024430,17,7167.58,-1501.69,962.569), +(2024450,1,6563.27,-811.767,749.876), +(2024450,2,6299.5,-797.577,529.126), +(2024450,3,6194.55,-1013.14,501.542), +(2024450,4,6319.25,-1251.66,468.626), +(2024450,5,6309.16,-1537.86,615.042), +(2024450,6,6748.21,-1664.31,919.312), +(2024450,7,6913.31,-1725.26,954.792), +(2024450,8,7167.58,-1501.69,962.569), +(2024450,9,7440.4,-1295.86,997.291), +(2024450,10,7024.75,-1625.54,957.369), +(2024450,11,7025.49,-1624.87,957.369), +(2024450,12,7167.58,-1501.69,962.569), +(2024450,13,7440.4,-1295.86,997.291), +(2024450,14,7210.96,-1046.89,1006.18), +(2024450,15,6998.46,-1076.85,1024.82), +(2024450,16,6874.25,-1097.38,927.736), +(2024450,17,6614.79,-875.755,812.765), +(2024470,1,6614.79,-875.755,812.765), +(2024470,2,6563.27,-811.767,749.876), +(2024470,3,6299.5,-797.577,529.126), +(2024470,4,6194.55,-1013.14,501.542), +(2024470,5,6319.25,-1251.66,468.626), +(2024470,6,6309.16,-1537.86,615.042), +(2024470,7,6748.21,-1664.31,919.312), +(2024470,8,6913.31,-1725.26,954.792), +(2024470,9,7167.58,-1501.69,962.569), +(2024470,10,7440.4,-1295.86,997.291), +(2024470,11,7024.75,-1625.54,957.369), +(2024470,12,7025.49,-1624.87,957.369), +(2024470,13,7167.58,-1501.69,962.569), +(2024470,14,7440.4,-1295.86,997.291), +(2024470,15,7210.96,-1046.89,1006.18), +(2024470,16,6998.46,-1076.85,1024.82), +(2024470,17,6874.25,-1097.38,927.736), +(2024510,1,6913.31,-1725.26,954.792), +(2024510,2,7167.58,-1501.69,962.569), +(2024510,3,7440.4,-1295.86,997.291), +(2024510,4,7024.75,-1625.54,957.369), +(2024510,5,7025.49,-1624.87,957.369), +(2024510,6,7167.58,-1501.69,962.569), +(2024510,7,7440.4,-1295.86,997.291), +(2024510,8,7210.96,-1046.89,1006.18), +(2024510,9,6998.46,-1076.85,1024.82), +(2024510,10,6874.25,-1097.38,927.736), +(2024510,11,6614.79,-875.755,812.765), +(2024510,12,6563.27,-811.767,749.876), +(2024510,13,6299.5,-797.577,529.126), +(2024510,14,6194.55,-1013.14,501.542), +(2024510,15,6319.25,-1251.66,468.626), +(2024510,16,6309.16,-1537.86,615.042), +(2024510,17,6748.21,-1664.31,919.312), +(2024520,1,7167.58,-1501.69,962.569), +(2024520,2,7440.4,-1295.86,997.291), +(2024520,3,7210.96,-1046.89,1006.18), +(2024520,4,6998.46,-1076.85,1024.82), +(2024520,5,6874.25,-1097.38,927.736), +(2024520,6,6614.79,-875.755,812.765), +(2024520,7,6563.27,-811.767,749.876), +(2024520,8,6299.5,-797.577,529.126), +(2024520,9,6194.55,-1013.14,501.542), +(2024520,10,6319.25,-1251.66,468.626), +(2024520,11,6309.16,-1537.86,615.042), +(2024520,12,6748.21,-1664.31,919.312), +(2024520,13,6913.31,-1725.26,954.792), +(2024520,14,7167.58,-1501.69,962.569), +(2024520,15,7440.4,-1295.86,997.291), +(2024520,16,7024.75,-1625.54,957.369), +(2024520,17,7025.49,-1624.87,957.369); diff --git a/sql/updates/world/2013_04_01_00_world_misc.sql b/sql/updates/world/2013_04_01_00_world_misc.sql new file mode 100644 index 00000000000..39b5d231c0f --- /dev/null +++ b/sql/updates/world/2013_04_01_00_world_misc.sql @@ -0,0 +1,20 @@ +DELETE FROM `spell_script_names` WHERE `spell_id`=45759; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(45759,'spell_gen_orc_disguise'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry`=45742; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(17,0,45742,0,0,1,0,45760,0,0,0,0,'','Spell Plant Warsong Banner can be casted only if player has aura Warsong Orc Disguise (Male)'), +(17,0,45742,0,0,31,1,3,25430,0,0,0,'','Spell Plant Warsong Banner can be casted only on Magmothregar'), +(17,0,45742,0,0,36,1,0,0,0,1,0,'','Spell Plant Warsong Banner can be casted only if target is dead'), +(17,0,45742,0,1,1,0,45762,0,0,0,0,'','Spell Plant Warsong Banner can be casted only if player has aura Warsong Orc Disguise (Female)'), +(17,0,45742,0,1,31,1,3,25430,0,0,0,'','Spell Plant Warsong Banner can be casted only on Magmothregar'), +(17,0,45742,0,1,36,1,0,0,0,1,0,'','Spell Plant Warsong Banner can be casted only if target is dead'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25430; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=25430; +DELETE FROM `smart_scripts` WHERE `entryorguid`=25430 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(25430,0,0,0,4,0,100,0,0,0,0,0,11,50413,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Magmothregar - On aggro - Spellcast Magnataur Charge'), +(25430,0,1,0,0,0,100,0,3500,12800,10100,14000,11,50822,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Magmothregar - On update IC - Spellcast Fervor'), +(25430,0,2,0,8,0,100,0,45742,0,0,0,11,45744,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Magmothregar - On spellhit Plant Warsong Banner - Spellcast It Was The Orcs, Honest!: Plant Banner Kill Credit'); diff --git a/sql/updates/world/2013_04_02_00_world_smart_scripts.sql b/sql/updates/world/2013_04_02_00_world_smart_scripts.sql new file mode 100644 index 00000000000..1687df8ff2d --- /dev/null +++ b/sql/updates/world/2013_04_02_00_world_smart_scripts.sql @@ -0,0 +1,12 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid`=19456 AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`id`,`link`,`event_type`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUES +(19456,0,0,54,0,0,0,0,0,42,0,25,1,'Whitebarks Spirit - On summon - Set invincibility HP at 25%'), +(19456,1,0,4,1,0,0,0,0,1,0,0,1,'Whitebarks Spirit - On aggro (not repeatable) - Say 0'), +(19456,2,3,2,0,24,26,120000,120000,102,0,0,1,'Whitebarks Spirit - 24-26% HP - Disable HP reg (video)'), +(19456,3,4,61,0,0,0,0,0,101,0,0,1,'Whitebarks Spirit - Linked - Set home position'), +(19456,4,5,61,0,0,0,0,0,2,35,0,1,'Whitebarks Spirit - Linked - Change faction to friendly'), +(19456,5,6,61,0,0,0,0,0,1,1,0,1,'Whitebarks Spirit - Linked - Say 1'), +(19456,6,0,61,0,0,0,0,0,24,0,0,1,'Whitebarks Spirit - Linked - evade'), +(19456,7,0,0,0,2500,5500,12000,14500,11,31287,0,2,'Whitebarks Spirit - IC - Casts Entangling Roots'), +(19456,8,0,0,0,7500,7500,9500,16000,11,11442,0,2,'Whitebarks Spirit - IC - Casts Withered Touch'), +(19456,9,0,1,0,60000,60000,60000,60000,41,0,0,1,'Whitebarks Spirit - After 60sec OOC - Despawn'); diff --git a/sql/updates/world/2013_04_02_01_world_gameobject.sql b/sql/updates/world/2013_04_02_01_world_gameobject.sql new file mode 100644 index 00000000000..120dd66eb0d --- /dev/null +++ b/sql/updates/world/2013_04_02_01_world_gameobject.sql @@ -0,0 +1,5 @@ +SET @OGUID := 1160; + +DELETE FROM `gameobject` WHERE `guid`=@OGUID; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES +(@OGUID, 202275, 530, 1, 1, -2186.307, -12341.81, 56.27893, 0, 0, 0, 0, 1, 120, 255, 1); -- Wrathscale Fountain diff --git a/sql/updates/world/2013_04_02_02_world_creature.sql b/sql/updates/world/2013_04_02_02_world_creature.sql new file mode 100644 index 00000000000..194eee288d2 --- /dev/null +++ b/sql/updates/world/2013_04_02_02_world_creature.sql @@ -0,0 +1,5 @@ +SET @CGUID := 40471; + +DELETE FROM `creature` WHERE `guid`=@CGUID; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(@CGUID, 23143, 530, 1, 1, -5142.569, 581.3281, 84.13567, 0.5061455, 120, 0, 0); -- Horus (Area: Netherwing Ledge) diff --git a/sql/updates/world/2013_04_03_00_world_command.sql b/sql/updates/world/2013_04_03_00_world_command.sql new file mode 100644 index 00000000000..3ce73686db3 --- /dev/null +++ b/sql/updates/world/2013_04_03_00_world_command.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help`='Syntax: .gobject info [$object_entry]\r \r Query Gameobject information for selected gameobject or given entry.' WHERE `name`='gobject info'; diff --git a/sql/updates/world/2013_04_03_01_world_trinity_string.sql b/sql/updates/world/2013_04_03_01_world_trinity_string.sql new file mode 100644 index 00000000000..b370664e4cf --- /dev/null +++ b/sql/updates/world/2013_04_03_01_world_trinity_string.sql @@ -0,0 +1,11 @@ +-- Add Trinity String for Spirit Guide and wintergrasp battle mage +DELETE FROM `trinity_string` WHERE `entry` IN (20071,20072,20074,20073,20070,20075,20076,20077); +INSERT INTO `trinity_string`(`entry`,`content_default`) VALUES +(20071, 'Guide me to the Sunken Ring Graveyard.'), +(20072, 'Guide me to the Broken Temple Graveyard.'), +(20074, 'Guide me to the Eastspark Graveyard.'), +(20073, 'Guide me to the Westspark Graveyard.'), +(20070, 'Guide me to the Fortress Graveyard.'), +(20075, 'Guide me back to the Horde landing camp.'), +(20076, 'Guide me back to the Alliance landing camp.'), +(20077, 'Queue for Wintergrasp.'); diff --git a/sql/updates/world/2013_04_03_02_world_sai.sql b/sql/updates/world/2013_04_03_02_world_sai.sql new file mode 100644 index 00000000000..8ae37e21ff2 --- /dev/null +++ b/sql/updates/world/2013_04_03_02_world_sai.sql @@ -0,0 +1,679 @@ +SET @HO_SOOSAY := 28027; +SET @HO_GOSSIP := 9742; +SET @O_STATE := 50503; +SET @T_STORM := 53071; +SET @FI_LAFOO := 52547; +SET @FI_JALOOT := 52548; +SET @FI_MOODLE := 52549; +SET @SEEINVIS := 52214; +SET @RAINSPEAKERAURA := 51639; +SET @TREASUREPING:= 51420; +SET @GORLOCPING := 51794; +SET @WOLVARPING := 51791; +SET @DIGUPGLINTINGBUG:= 51443; +SET @DIGUPSPARKINGHARE := 51441; +SET @DIGUPSHININGCRYSTAL := 51397; +SET @DIGUPGLINTINGARMOR := 51398; +SET @DIGUPGLOWINGGEM := 51400; +SET @DIGUPPOLISHEDPLATTER := 51401; +SET @DIGUPSPARKINGTREASURE := 51402; +SET @BLESSINGOFTHESPARKINGHARE := 51442; +SET @JALOOTSINTENSITY := 52119; +SET @RAINSPEAKERBUNNY := 28455; +SET @LAFOO := 28120; +SET @MOODLE := 28122; +SET @JALOOT := 28121; +SET @GLINTINGDIRT := 28362; +SET @GLINTINGBUG := 28372; +SET @SPARKLINGHARE := 28371; +SET @GLINTINGDIRTSCRIPT := 2836201; +SET @GORLOCTREASURESCRIPT := 2812000; +SET @ELDER_HARKEK := 28138; +SET @SHAMAN_RAKJAK := 28082; +SET @EH_GOSSIP:= 9741; +SET @FRENZYAURA := 51234; +SET @FRENZYBUNNY := 28299; +SET @GOREGEK := 28214; +SET @DAJIK := 28215; +SET @ZEPIK := 28216; +SET @FI_GOREGEK := 52542; +SET @FI_DAJIK := 52544; +SET @FI_ZEPIK := 52545; +SET @CHICKENSEEINVIS := 50735; +SET @DESSAWNRETAINER := 53163; +SET @MOSSWALKERAURA := 51644; +SET @MOSSWALKERBUNNY := 28459; +SET @ANGRYGORLOCCREDIT := 54057; +SET @MISTWHISPERAURA := 51239; +SET @MISTWHISPERBUNNY := 28300; +SET @SPEARBORNAURA := 51642; +SET @SPEARBORNBUNNY := 28457; +SET @KARTAKHOLDAURA := 51643; +SET @KARTAKHOLDBUNNY := 28458; +SET @SPARKTOUCHEDAURA := 51641; +SET @SPARKTOUCHEDBUNNY := 28456; +SET @SAPPHIREHIVEAURA := 51651; +SET @LIFEBLOODPILLARBUNNY := 28460; +SET @LIFEBLOODPILLARAURA:= 51649; +SET @SKYREACHPILLARBUNNY := 28454; +SET @SKYREACHPILLARAURA:= 51645; +SET @SAPPHIREHIVEBUNNY := 28462; +SET @GORLOCLOCATIONPERIODIC := 51793; +SET @WOLVARLOCATIONPERIODIC := 51792; +SET @LOOKINGFORTREASUREAURA := 51407; +SET @SHOLAZARGUARDIANHEARTBEAT := 51623; +SET @DIGGINGFORTEASURE := 51405; +SET @GOREGEKSSHACKLE := 38619; +SET @DAJIKSCHALK := 38621; +SET @ZEPIKSHUNTINGHORN := 38512; +SET @LAFOOSBUGBAG := 38622; +SET @JALOOTSCRYSTAL := 38623; +SET @MOODLESSTRESSBALL := 38624; +SET @INVISIBILTY := 52213; +SET @HARDKNUCKLE := 28096; +SET @HARDKNUCKLEMATRIARCH := 28213; +SET @SAPPHIREQUEEN := 28087; +SET @VENOMTIP := 28358; + +UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `exp`=2,`mindmg`=371, `maxdmg`=522,`attackpower`=478 WHERE `entry`IN (@GOREGEK,@DAJIK,@ZEPIK); +UPDATE `creature_template` SET `unit_flags` =33555200 WHERE `entry`IN (@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry` IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK); +DELETE FROM `creature_ai_scripts` WHERE `creature_id`IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK);; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@HO_SOOSAY, 0, 0, 0, 1, 0, 100, 0, 0, 0, 0, 0, 75, @O_STATE, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - Out of combat - Add Oracle State Aura'), +(@HO_SOOSAY, 0, 1, 0, 0, 0, 100, 0, 5000, 10000, 12000, 16000, 11, @T_STORM, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - In Combat - Cast Thunderstorm'), +(@HO_SOOSAY,0,2,8,62,0,100,0,@HO_GOSSIP,0,0,0,85,@FI_LAFOO,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Lafoo'), +(@HO_SOOSAY,0,3,8,62,0,100,0,@HO_GOSSIP,1,0,0,85,@FI_LAFOO,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Lafoo'), +(@HO_SOOSAY,0,4,8,62,0,100,0,@HO_GOSSIP,2,0,0,85,@FI_JALOOT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Jaloot'), +(@HO_SOOSAY,0,5,8,62,0,100,0,@HO_GOSSIP,3,0,0,85,@FI_JALOOT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Jaloot'), +(@HO_SOOSAY,0,6,8,62,0,100,0,@HO_GOSSIP,4,0,0,85,@FI_MOODLE,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Moodle'), +(@HO_SOOSAY,0,7,8,62,0,100,0,@HO_GOSSIP,5,0,0,85,@FI_MOODLE,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Moodle'), +(@HO_SOOSAY,0,8,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Close gossip'), +(@HO_SOOSAY,0,9, 0, 20, 0, 100, 0, 12704, 0, 0, 0, 28, @SEEINVIS, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Complete - Remove Aura Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY,0,10, 0, 19, 0, 100, 0, 12704, 0, 0, 0, 85, @SEEINVIS, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Invoker Cast Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY, 0, 11, 0, 20, 0, 100, 0, 12572, 0, 0, 0, 28, @SEEINVIS, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Complete - Remove Aura Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY, 0, 12, 0, 19, 0, 100, 0, 12574, 0, 0, 0, 57, @LAFOOSBUGBAG, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Remove Lafoos Bug bag'), +(@HO_SOOSAY, 0, 13, 0, 20, 0, 100, 0, 12577, 0, 0, 0, 57, @JALOOTSCRYSTAL, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Complete - Remove Jaloots favourite crystal'), +(@HO_SOOSAY, 0, 14, 0, 20, 0, 100, 0, 12581, 0, 0, 0, 57, @MOODLESSTRESSBALL, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Complete - Remove Moodles Stress Ball'), +-- +(@SHAMAN_RAKJAK,0,0,0,19,0,100,0,12529,0,0,0,11,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Goregek'), +(@SHAMAN_RAKJAK,0,1,0,19,0,100,0,12530,0,0,0,11,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Goregek'), +(@SHAMAN_RAKJAK,0,2,0,19,0,100,0,12533,0,0,0,11,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Dajik'), +(@SHAMAN_RAKJAK,0,3,0,19,0,100,0,12534,0,0,0,11,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Dajik'), +(@SHAMAN_RAKJAK,0,4,0,19,0,100,0,12536,0,0,0,11,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Zepik'), +(@SHAMAN_RAKJAK, 0, 15, 0, 19, 0, 100, 0, 12533, 0, 0, 0, 57, @GOREGEKSSHACKLE, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - On Quest Accept - Remove Goregeks Shackes'), +(@SHAMAN_RAKJAK, 0, 16, 0, 19, 0, 100, 0, 12536, 0, 0, 0, 57, @DAJIKSCHALK, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - On Quest Accept - Remove Dajiks Chalk'), +(@SHAMAN_RAKJAK, 0, 17, 0, 19, 0, 100, 0, 12540, 0, 0, 0, 57, @ZEPIKSHUNTINGHORN, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - On Quest Accept - Remove Zepiks Hunting Horn'), +-- +(@ELDER_HARKEK,0,4,10,62,0,100,0,@EH_GOSSIP,0,0,0,85,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Goregek'), +(@ELDER_HARKEK,0,5,10,62,0,100,0,@EH_GOSSIP,1,0,0,85,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Goregek'), +(@ELDER_HARKEK,0,6,10,62,0,100,0,@EH_GOSSIP,2,0,0,85,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Dajik'), +(@ELDER_HARKEK,0,7,10,62,0,100,0,@EH_GOSSIP,3,0,0,85,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Dajik'), +(@ELDER_HARKEK,0,8,10,62,0,100,0,@EH_GOSSIP,4,0,0,85,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Zepik'), +(@ELDER_HARKEK,0,9,10,62,0,100,0,@EH_GOSSIP,5,0,0,85,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Zepik'), +(@ELDER_HARKEK,0,10,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Close gossip'), +(@ELDER_HARKEK, 0, 3, 0, 20, 0, 100, 0, 12702, 0, 0, 0, 28, @CHICKENSEEINVIS, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Elder Harkek - On Quest Complete - Remove Aura Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK, 0, 2, 0, 20, 0, 100, 0, 12532, 0, 0, 0, 28, @CHICKENSEEINVIS, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Elder Harkek - On Quest Complete - Remove Aura Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK, 0, 1, 0, 19, 0, 100, 0, 12702, 0, 0, 0, 85, @CHICKENSEEINVIS, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Elder Harkek - On Quest Accept - Invoker Cast Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK, 0, 0, 0, 19, 0, 100, 0, 12532, 0, 0, 0, 85, @CHICKENSEEINVIS, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Elder Harkek - On Quest Accept - Invoker Cast Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK, 0, 11, 0, 19, 0, 100, 0, 12534, 0, 0, 0, 57, @GOREGEKSSHACKLE, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Elder Harkek - On Quest Accept - Remove Goregeks Shackes'); +-- +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN(@HO_GOSSIP,@EH_GOSSIP) AND `id` IN(0,1,2,3,4,5); +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(@HO_GOSSIP,0,0, 'I need to find Lafoo, do you have his bug bag?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,1,0, 'I need to find Lafoo, do you have his bug bag?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,2,0, 'I need to find Jaloot, do you have his favorite crystal?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,3,0, 'I need to find Jaloot, do you have his favorite crystal?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,4,0, 'I need to find Moodle, do you have his stress ball?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,5,0, 'I need to find Moodle, do you have his stress ball?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,0,0, 'I need to find Goregek, do you have his shackles?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,1,0, 'I need to find Goregek, do you have his shackles?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,2,0, 'I need to find Dajik, do you have his chalk?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,3,0, 'I need to find Dajik, do you have his chalk?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,4,0, 'I need to find Zepik, do you have his hunting horn?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,5,0, 'I need to find Zepik, do you have his hunting horn?',1,1,0,0,0,0, ''); +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`IN(@HO_GOSSIP,@EH_GOSSIP); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@HO_GOSSIP,0,0,0,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,0,9,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,2,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,2,8,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,1,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,1,28,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has completed Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,0,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,0,0,1,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,0,0,2,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,1,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,1,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,1,0,0,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,4,0,0,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,0,9,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,2,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,2,8,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,1,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,1,28,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,0,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,1,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,2,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,3,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,3,9,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,5,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,5,8,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,4,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,4,28,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,3,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,4,0,4,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,4,0,5,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,5,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,5,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,5,0,0,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Jaloot''s Favorite Crystal'), +(15,@HO_GOSSIP,2,0,0,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,0,9,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest Back so soon?'), +(15,@HO_GOSSIP,2,0,2,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,2,8,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Back so soon?'), +(15,@HO_GOSSIP,2,0,1,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,1,28,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Back so soon?'), +(15,@HO_GOSSIP,2,0,0,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,2,0,1,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,2,0,2,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,3,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,3,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,3,0,0,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Moodle''s Stress Ball'), +(15,@EH_GOSSIP,0,0,0,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,0,9,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,2,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,2,8,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,1,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,1,28,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,3,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,3,9,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,4,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,4,8,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,5,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,5,28,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,0,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,1,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,2,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,3,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,4,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,5,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,0,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,1,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,2,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,3,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,4,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,5,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,2,0,0,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,0,9,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,2,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,2,8,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,1,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,1,28,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,3,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,3,9,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,4,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,4,8,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,5,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,5,28,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,0,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,1,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,2,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,3,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,4,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,5,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,0,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,0,9,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,2,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,2,8,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,1,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,1,28,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,0,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'), +(15,@EH_GOSSIP,4,0,1,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'), +(15,@EH_GOSSIP,4,0,2,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'); +-- +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15, @EH_GOSSIP,1,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15, @EH_GOSSIP,1,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15, @EH_GOSSIP,1,0,2,@GOREGEKSSHACKLE,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Goregek''s Shackles'), +(15, @EH_GOSSIP,3,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15, @EH_GOSSIP,3,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15, @EH_GOSSIP,3,0,2,@DAJIKSCHALK,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Dajiks Worn Chalk'), +(15, @EH_GOSSIP,5,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15, @EH_GOSSIP,5,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15, @EH_GOSSIP,5,0,2,@ZEPIKSHUNTINGHORN,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Zepiks Hunting Horn'); +-- Jaloot's Itensity and Blessing of the Sparkling Hare don't stack +DELETE FROM `spell_group` WHERE `id`=@BLESSINGOFTHESPARKINGHARE; +INSERT INTO `spell_group` (`id`, `spell_id`) VALUES +(@BLESSINGOFTHESPARKINGHARE, @BLESSINGOFTHESPARKINGHARE), +(@BLESSINGOFTHESPARKINGHARE, @JALOOTSINTENSITY); + +DELETE FROM `spell_group_stack_rules` WHERE `group_id`=@BLESSINGOFTHESPARKINGHARE; +INSERT INTO `spell_group_stack_rules` (`group_id`,`stack_rule`) VALUES +(@BLESSINGOFTHESPARKINGHARE,1); +DELETE FROM `creature_template_addon` WHERE `entry`IN(@GLINTINGDIRT,@LAFOO,@JALOOT,@MOODLE,@GLINTINGBUG,@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(@GLINTINGBUG,0,0,0,1,0, '51444'), +(@GOREGEK,0,0,0,1,0, '54178'), +(@DAJIK,0,0,0,1,0, '52734'), +(@ZEPIK,0,0,0,1,0, '54176'); +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=@SEEINVIS AND `spell_effect`=@LOOKINGFORTREASUREAURA; +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(@SEEINVIS,@LOOKINGFORTREASUREAURA,2, 'Looking for treasure aura triggered by Rainspeaker Treasures: See Invisibility'); +DELETE FROM `spell_area` WHERE `spell` =@ANGRYGORLOCCREDIT; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@GLINTINGDIRT; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@GLINTINGDIRT; +DELETE FROM `smart_scripts` WHERE `entryorguid` BETWEEN @GLINTINGDIRTSCRIPT AND @GLINTINGDIRTSCRIPT+5; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@GLINTINGDIRT,0,0 ,0,38, 0,100,1,1,1,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - On Data Set - Increment Phase'), +(@GLINTINGDIRT,0,1 ,0,1, 1,100,1,0,0,0,0,87,@GLINTINGDIRTSCRIPT,@GLINTINGDIRTSCRIPT+1,@GLINTINGDIRTSCRIPT+2,@GLINTINGDIRTSCRIPT+3,@GLINTINGDIRTSCRIPT+4,@GLINTINGDIRTSCRIPT+5,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Run Random Script'), +(@GLINTINGDIRT,0,2 ,0,1, 1,100,1,400,400,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Despawn'), +(@GLINTINGDIRT,0,3 ,0,11, 0,100,0,0,0,0,0,11,@INVISIBILTY,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - On Spawn - Cast Rainspeaker Treasures: Invisibility'), +(@GLINTINGDIRTSCRIPT,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSPARKINGHARE,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Sparking Hare'), +(@GLINTINGDIRTSCRIPT,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+1,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSHININGCRYSTAL,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Shining Crystal'), +(@GLINTINGDIRTSCRIPT+1,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+2,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPGLINTINGARMOR,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Glinting Armor'), +(@GLINTINGDIRTSCRIPT+2,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+3,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPGLOWINGGEM,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Glowing Gem'), +(@GLINTINGDIRTSCRIPT+3,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+4,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPPOLISHEDPLATTER,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Polished Platter'), +(@GLINTINGDIRTSCRIPT+4,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+5,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSPARKINGTREASURE,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Sparking Treasure'), +(@GLINTINGDIRTSCRIPT+5,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN(@RAINSPEAKERBUNNY,@FRENZYBUNNY,@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +UPDATE `creature_template` SET `AIName`= 'SmartAI',`unit_flags`=32776,`InhabitType`=3 WHERE `entry`In(@LAFOO,@MOODLE,@JALOOT,@GOREGEK,@DAJIK,@ZEPIK); +UPDATE `creature_template` SET `gossip_menu_id`=9747, `npcflag`=`npcflag`|1, `speed_run`=1.30952 WHERE `entry`=@JALOOT; +UPDATE `creature_template` SET `npcflag`=`npcflag`|1, `speed_run`=1.19048 WHERE `entry`=@MOODLE; +UPDATE `gossip_menu_option` SET `action_menu_id`=9684 WHERE `menu_id`=9677; +UPDATE `creature_template` SET `gossip_menu_id`=9745 WHERE `entry`=28106; +UPDATE `creature_template` SET `speed_walk`=0.66667, `speed_run`=0.99206 WHERE `entry`=@GOREGEK; +UPDATE `creature_template` SET `speed_walk`=0.66667, `speed_run`=0.99206, `npcflag`=`npcflag`|1 WHERE `entry`=@ZEPIK; +UPDATE `gossip_menu_option` SET `action_menu_id`=9684 WHERE `menu_id`=9677; +DELETE FROM `creature_involvedrelation` WHERE `id`=28216 AND `quest`=12582; + +DELETE FROM `gossip_menu` WHERE `entry`=9747; +DELETE FROM `gossip_menu` WHERE `entry`=9562 AND `text_id`=12883; +DELETE FROM `gossip_menu` WHERE `entry`=9570 AND `text_id`=12905; +DELETE FROM `gossip_menu` WHERE `entry`=9678 AND `text_id`=13136; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9562,12883), +(9570,12905), +(9678,13136), +(9747,13367); + +DELETE FROM `npc_text` WHERE `ID`=13136; +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(13136,'Vekjik no want to be bothered.','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340); + +DELETE FROM `creature_equip_template` WHERE `entry` IN (@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_equip_template` (`entry`,`id`,`itemEntry1`,`itemEntry2`,`itemEntry3`) VALUES +(@GOREGEK,1,36488,0,0), +(@DAJIK,1,28325,0,0), +(@ZEPIK,1,28914,0,5258); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(@LAFOO,@MOODLE,@JALOOT,@GOREGEK,@DAJIK,@ZEPIK,@GORLOCTREASURESCRIPT,@RAINSPEAKERBUNNY,@FRENZYBUNNY,@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@GOREGEK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Set React State'), +(@GOREGEK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Say line'), +(@GOREGEK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Despawn'), +(@GOREGEK,0,3,0,0,0,100,0,3000,6000,8000,16000,11,54188,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Goregek - IC - Cast Sunder Armor'), +(@GOREGEK,0,4,0,0,0,100,0,5000,8000,15000,20000,11,52743,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Goregek - IC - Cast Head Smack'), +(@GOREGEK,0,5,0,2,0,100,0,0,30,60000,60000,11,52748,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Less than 30% HP - Cast Voracious Appetite'), +(@GOREGEK,0,6,0,13,0,100,0,12000,20000,0,0,11,6713,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Target Casting - Cast Disarm'), +(@GOREGEK,0,7 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Creature Death - Say'), +(@GOREGEK,0,8 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Gorekek - OOC - Say'), +(@GOREGEK,0,9 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Cast Wolvar Location Periodic'), +(@GOREGEK,0,10 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@GOREGEK,0,11 ,0,1,0,100,0,10000,40000,45000,90000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Gorekek - OOC - Say'), +(@GOREGEK,0,12 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - OOC - Set Phase 2'), +(@GOREGEK,0,13 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Agro - Set Phase 1'), +(@GOREGEK,0,14 ,0,38,0,100,0,1,1,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Data Set - Say'), +(@GOREGEK,0,15,0,8,2,100,0,@KARTAKHOLDAURA,0,40000,70000,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Say line'), +(@DAJIK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Spawn - Set React State'), +(@DAJIK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Despawn'), +(@DAJIK,0,3,0,0,0,100,0,3000,6000,8000,12000,11,54195,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Dajik - IC - Cast Earth''s Wrath'), +(@DAJIK,0,4,0,0,0,100,0,5000,8000,15000,20000,11,54193,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Dajik - IC - Cast Earth''s Fury'), +(@DAJIK,0,5,0,2,0,100,0,0,30,60000,60000,11,54206,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Less than 30% HP - Cast Mend'), +(@DAJIK,0,6 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death - Say'), +(@DAJIK,0,8 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Say'), +(@DAJIK,0,9,0,8,2,100,0,@SAPPHIREHIVEAURA,0,40000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,10 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Spawn - Cast Wolvar Location Periodic'), +(@DAJIK,0,11 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik -Goregek - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@DAJIK,0,12 ,0,38,0,100,0,1,1,0,0,1,4,5000,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death (Sapphire Queen) - Say'), +(@DAJIK,0,13 ,0,38,0,100,0,1,2,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death (Serfex the Reaver) - Say'), +(@DAJIK,0,14 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Set Phase 2'), +(@DAJIK,0,15 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Agro - Set Phase 1'), +(@DAJIK,0,16 ,0,52,0,100,0,4,@DAJIK,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik On - Text Over - Say'), +(@DAJIK,0,17,0,8,2,100,0,@SKYREACHPILLARAURA,0,40000,70000,1,7,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,18 ,0,1,0,100,0,10000,40000,45000,90000,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Say'), +(@DAJIK,0,19,0,8,2,100,0,@LIFEBLOODPILLARAURA,0,40000,70000,1,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@ZEPIK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Set React State'), +(@ZEPIK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Say line'), +(@ZEPIK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Despawn'), +(@ZEPIK,0,3,0,0,0,100,0,4000,7000,15000,18000,11,52761,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Barbed Net'), +(@ZEPIK,0,4,0,0,0,100,0,5000,8000,12000,15000,11,52889,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Envenomed Shot'), +(@ZEPIK,0,5,0,0,0,100,0,0,6000,15000,18000,11,52873,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Open Wound'), +(@ZEPIK,0,6,0,0,0,100,0,3000,5000,3000,7000,11,52758,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Piercing Arrow'), +(@ZEPIK,0,7,0,2,0,100,0,0,30,60000,60000,11,52895,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - On Less than 30% HP Cast Bandage - Cast Bandage'), +(@ZEPIK,0,8 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Creature Death - Say'), +(@ZEPIK,0,9 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - OOC - Say'), +(@ZEPIK,0,10,0,8,2,100,0,@MISTWHISPERAURA,0,40000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Say line'), +(@ZEPIK,0,11 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Cast Wolvar Location Periodic'), +(@ZEPIK,0,12 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@ZEPIK,0,13 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - OOC - Set Phase 2'), +(@ZEPIK,0,14 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Agro - Set Phase 1'), +(@ZEPIK,0,15 ,0,38,0,100,0,1,2,0,0,1,4,5000,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Data Set - Say'), +(@ZEPIK,0,16 ,0,52,0,100,0,4,@ZEPIK,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Text Over - Say'), +(@LAFOO,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spellhit - Say'), +(@LAFOO,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Linked with Previous Event - Run Script'), +(@LAFOO,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Cast Gorloc Location Periodic'), +(@LAFOO,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@LAFOO,0,4 ,0,38, 0,100,0,1,1,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Data Set - Say'), +(@GORLOCTREASURESCRIPT,9,0 ,0,61, 0,100,0,0,0,0,0,69,0,0,0,0,0,0,11,28362,10,0,0,0,0,0, 'Lafoo - Script - Move to Glinting Dirt'), +(@GORLOCTREASURESCRIPT,9,1 ,0,61, 0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,9,@GLINTINGDIRT,0,2,0,0,0,0, 'Lafoo - Script - Set Data'), +(@GORLOCTREASURESCRIPT,9,2 ,0,61, 0,100,0,1500,1500,0,0,11,51405,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Script - Cast Digging for Treasure'), +(@GORLOCTREASURESCRIPT,9,3 ,0,61, 0,100,0,5000,5000,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Script - Evade'), +(@LAFOO,0,6 ,0,0, 0,100,0,0,5000,10000,12000,11,52931,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Lafoo - IC - Cast Toxic Spit'), +(@LAFOO,0,7 ,0,2,0,100,0,0,50,60000,60000,11,52940,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Friendly Health - Cast Sleepy Time'), +(@LAFOO,0,8 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Set React State'), +(@LAFOO,0,9 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Creature Death - Say'), +(@LAFOO,0,10 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - OOC - Say'), +(@LAFOO,0,11,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On spellhit - Say line'), +(@LAFOO,0,12,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On spellhit - Despawn'), +(@LAFOO,0,13,0,19,0,100,0,12572,0,0,0,85,@SEEINVIS,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Lafoo - On Quest Accept - Invoker Cast Rainspeaker Treasures: See Invisibility'), +(@LAFOO,0,14 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - OOC - Set Phase 2'), +(@LAFOO,0,15 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Agro - Set Phase 1'), +(@JALOOT,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spellhit - Say'), +(@JALOOT,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - Linked with Previous Event - Run Script'), +(@JALOOT,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Gorloc Location Periodic'), +(@JALOOT,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@JALOOT,0,4 ,0,38, 0,100,0,1,1,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Data Set - Say'), +(@JALOOT,0,6,0,0,0,100,0,9000,15000,20000,25000,11,52943,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Lightning Whirl'), +(@JALOOT,0,7,0,0,0,100,0,5000,8000,15000,18000,11,52944,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Lightning Strike'), +(@JALOOT,0,8,0,0,0,100,0,7000,15000,20000,25000,11,52964,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Spark Frenzy'), +(@JALOOT,0,9,0,2,0,100,0,0,30,30000,45000,11,52969,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Less than 30% HP - Cast Energy Siphon'), +(@JALOOT,0,10 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Set React State'), +(@JALOOT,0,11 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Creature Death - Say'), +(@JALOOT,0,12 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - OOC - Say'), +(@JALOOT,0,13,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Say line'), +(@JALOOT,0,14,0,11,0,100,0,0,0,0,0,11,@JALOOTSINTENSITY,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Jaloot''s Intensity'), +(@JALOOT,0,15,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Despawn'), +(@JALOOT,0,16,0,8,2,100,0,@SPEARBORNAURA,0,40000,70000,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Say line'), +(@JALOOT,0,17 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - OOC - Set Phase 2'), +(@JALOOT,0,18 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Agro - Set Phase 1'), +(@MOODLE,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spellhit - Say'), +(@MOODLE,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - Linked with Previous Event - Run Script'), +(@MOODLE,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Cast Gorloc Location Periodic'), +(@MOODLE,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@MOODLE,0,4 ,0,0, 0,100,0,0,5000,20000,30000,11,52974,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - IC - Cast Vicious Roar'), +(@MOODLE,0,5 ,0,20, 0,100,0,12580,0,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Quest Complete - Say'), +(@MOODLE,0,6 ,0,0, 0,100,0,0,5000,20000,24000,11,52973,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Moodle - IC - Cast Frost Breath'), +(@MOODLE,0,7,0,0,0,100,0,9000,15000,20000,25000,11,52979,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Moodle - IC - Cast Whirlwind'), +(@MOODLE,0,8,0,0,0,100,0,2000,10000,40000,50000,11,52972,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - IC - Cast Dispersal'), +(@MOODLE,0,9 ,0,2,0,100,0,0,50,60000,60000,11,52979,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On less than 50% HP - Cast Frigid Absorbtion'), +(@MOODLE,0,10 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Set React State'), +(@MOODLE,0,11 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Creature Death - Say'), +(@MOODLE,0,12 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - OOC - Say'), +(@MOODLE,0,13,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Say line'), +(@MOODLE,0,14,0,8,0,100,1,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Despawn'), +(@MOODLE,0,15,0,8,2,100,0,@MOSSWALKERAURA,0,40000,70000,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Say line'), +(@MOODLE,0,16 ,0,61, 0,100,0,0,0,0,0,8,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - Linked with Previous Event - Run Passive'), +(@MOODLE,0,17 ,0,19, 0,100,0,12581,0,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Quest Accept - Say'), +(@MOODLE,0,18 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - OOC - Set Phase 2'), +(@MOODLE,0,19 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Agro - Set Phase 1'), +(@RAINSPEAKERBUNNY,0,0,0,10,0,100,0,1,150,10000,10000,11,@RAINSPEAKERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Rainspeaker Canopy Bunny - On update OOC - Spellcast Rainspeaker Canopy Aura'), +(@FRENZYBUNNY,0,0,0,10,0,100,0,1,150,10000,10000,11,@FRENZYAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Frenzyheart Hill Bunny - On update OOC - Spellcast Frenzyheart Hill Aura'), +(@MOSSWALKERBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@MOSSWALKERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Mosswalker Village Bunny - On update OOC - Spellcast Mosswalker Village Aura'), +(@MOSSWALKERBUNNY,0,1,0,10,0,100,0,1,200,1000,1000,85,@ANGRYGORLOCCREDIT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Mosswalker Village Bunny - On update OOC - Cast quest credit'), +(@MISTWHISPERBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@MISTWHISPERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Mistwhisper Refuge Bunny - On update OOC - Spellcast Mistwhisper Refuge Aura'), +(@SPEARBORNBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SPEARBORNAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Spearborn Encampment Bunny - On update OOC - Spellcast Spearborn Encampment Aura'), +(@KARTAKHOLDBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@KARTAKHOLDAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Kartak Hold Bunny - On update OOC - Spellcast Kartak Hold Aura'), +(@SPARKTOUCHEDBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SPARKTOUCHEDAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sparktouched Haven Bunny - On update OOC - Spellcast Sparktouched Haven Aura'), +(@SAPPHIREHIVEBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SAPPHIREHIVEAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sapphire Hive Bunny - On update OOC - Spellcast Sapphire Hive Aura'), +(@SKYREACHPILLARBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SKYREACHPILLARAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Skyreach Pillar Bunny - On update OOC - Spellcast Skyreach Pillar Aura'), +(@LIFEBLOODPILLARBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@LIFEBLOODPILLARAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Lifeblood Pillar Bunny - On update OOC - Spellcast Lifeblood Pillar Aura'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@SPARKLINGHARE; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@SPARKLINGHARE; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@SPARKLINGHARE,0,0 ,0,6, 0,100,0,0,0,0,0,11,@BLESSINGOFTHESPARKINGHARE,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sparking Hare - On Death - Cast Blessing of the Sparkling Hare'); + +DELETE FROM `creature_text` WHERE `entry` IN(@LAFOO,@JALOOT,@MOODLE,@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@LAFOO, 0, 0, 'Ooh! Shinies!', 12, 0, 18, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 1, 'Maybe more shiny bugs! We like bugs!', 12, 0, 17, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 2, 'Treasure for Lafoo! Treasure for shrine!', 12, 0, 17, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 3, 'Dig, dig, dig...', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 4, 'Crunchy bugs so delicious. Want?', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 5, 'That weird. Someone took our bugs. You have maybe?', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 1, 0, 'No come back this time!', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 0, 'One day maybe you can be Soo-dryskin. You like?', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 1, 'You have pie? Someone gave us pie year ago. Really yummy.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 2, 'Big comfy tree. Good Home.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 3, 'Never meet Great Ones. Nope, just met their shrines.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 4, 'You got funny looking eyeballs.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 3, 0, 'Home good, but not stay long! More adventures!.', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@LAFOO, 4, 0, 'Hiss... hiss... dead. All dead', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@JALOOT, 0, 0, 'Shiny things! Shiny things! Not as shiny as my crystal, but still shiny!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 1, 'More treasures! Treasures of all kinds! Yay treasures!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 2, 'Can never have too many shiny crystals! Nope!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 3, 'We are fast digger! Really fast! See... all done! That was fast, huh?', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 0, 'You like that? Bet not! Bet not cause you dead! Hahah!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 1, 'Vic...tor...ious! Dun nun nun dun da da!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 2, 'Killing Spree!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 0, 'Mistcaller really good at controlling weather with shrine. They know just which crystals to use! Really good!', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 1, 'Ever trip over own feet? We have. Kind of hurt. No do it, not fun. Nope.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 2, 'Want us to help with something? What we help with? We good at helping.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 3, 'Hello! You''re pretty strong and nice and stuff. I like you. Lets stay friends, okay?', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 4, 'Misty. Very misty. Seem sort of misty to you? Maybe not so much.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 5, 'Lets go jump off tree! Fun fun!', 12, 0, 15, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 0, 'Chase the hatchlings! Chase the hatchlings! So fast!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 1, 'Great Ones keep home safe because they like Oracles I think! They know we good and nice.', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 2, 'Home home home... place of the shinies!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 0, 'We know you have dragon thing! We not scared! We going to get you and dragon thing!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 1, 'Teach you to steal our treasures! Our treasures are... ours, okay?', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 2, 'Time to hide puppy-men! We are coming for you!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 5, 0, 'Tartek no match for you! You got the skills. Yeah!', 12, 0, 100, 0, 0, 0, 'Jaloot'), +(@MOODLE, 0, 0, 'What the heck are shiny rabbits doing here anyway?', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 1, 'Here I am, digging up some useless bauble on the will of someone I just met...does that seem right to you?', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 2, 'Hey, maybe we''ll find some more useless bugs!', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 3, 'Yay... more dirt.', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 1, 0, 'I can''t believe ... they''re all ... dead', 12, 0, 50, 0, 0, 0, 'Moodle'), +(@MOODLE, 1, 1, 'Another one falls to our Onslaught, As it should be.', 12, 0, 50, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 0, 'There some reason why we''re still here? I''d love to hear it', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 1, 'Yeah, let''s go now', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 2, 'I''m done here', 12, 0, 34, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 0, 'Going to go take a nap? I apologize in advance for accidentally stepping on your face while you sleep.', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 1, 'Planning to sit on your butt some more, or are we going to go do something that''s actually useful?', 12, 0, 34, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 2, 'Here I am, brain the size of a planet, and they ask me to take you to the other village. Call that job satisfaction? ''Cause I don''t.', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 0, 'The Mosswalkers were good people... they did not deserve this.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 1, 'I know I talk down to them, but I never want to see any of my people die.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 2, 'It''s good to see some of the mosswalker were more resilient than I thought.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 3, 'It''s hard to believe any of them survived this.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 4, 'There are more that might still be alive! We need to keep moving.', 12, 0, 16, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 5, 'Where are they dragging those bodies? What are they doing to them?', 12, 0, 16, 0, 0, 0, 'Moodle'), +(@MOODLE, 5, 0, 'This fight''s all yours', 12, 0, 10, 0, 0, 0, 'Moodle'), +(@MOODLE, 6, 0, 'It''s a small comfort to see that they haven''t brought any back in undeath.', 12, 0, 100, 0, 0, 0, 'Moodle'), +(@GOREGEK,0,0,'Home! You better have brought back meat for Goregek, slave.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,1,'Goregek get some sleep. Go bring foodstuffs back, slave thing.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,2,'Goregek go get drink. You sit in corner til Goregek ready.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,3,'Goregek hungry. Go get on fire spit, slave thing. Tell Goregek when you well roasted.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,4,'Gorgek gonna catch chicken good!',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,5,'You wait until Goregek ready.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,6,'You wait, slave thing. Goregek eating.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,1,0,'Goregek best hunter... ever.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,1,'Hah! Goregek''s kill!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,2,'Next time, maybe Goregek let you try.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,3,'I stabbed it in the face! Goregek so good.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,4,'Squeal! Squeal! So good!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,5,'Frenzyheart the strongest!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,6,'That how it done, slave thing. Maybe you figure out how someday.',12,0,10,0,0,0,'Goregek'), +(@GOREGEK,2,0,'Why Goregek even bring you. You useless.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,1,'Elder maybe says other stuff, but you always be slave thing to Goregek.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,2,'Pitch was weakling anyway... why else you think Goregek not bother with him?',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,3,'You just get yourself beat up! Hah! You so dumb, slave thing.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,3,0,'Careful slave thing, the big bad softnuckles might eat you! Hah!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,1,'Hardknuckles still walk on hands... seem kind of dumb to Goregek.',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,2,'Run away dumb softknuckle! We gonna poke you more!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,3,'Run away softknuckle! Goregek gonna get you!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,4,'You just watch slave thing, Goregek take care of these hardknuckles!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,5,'Better not get in Goregek''s way!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,6,'Get out of way silly slave thing! Goregek''s kill!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,7,'There were hundreds of times these hardknuckles before Goregek.',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,4,0,'Hah! Goregek the greatest hunter ever! Goregek get biggest hardknuckle!',12,0,100,0,0,0,'Goregek'), +(@GOREGEK,5,0,'Frenzyheart feed Kartak big-tongue so Kartak not eat us. That why we smarter than you, slave thing.',12,0,100,0,0,0,'Goregek'), +(@DAJIK,0,0,'Frenzyheart came here not long ago for new home... big-tongue homes pretty nice, so we maybe take those too. They ugly anyway.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,1,'Lot of strong Frenzyheart here. Dajik taught most of them. First time I teach something like you though. You not a Frenzyheart, you know.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,2,'Let''s just eat bristlepine instead, okay? All done with chasing.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,3,'There reason Frenzyheart not chase back chickens. Look kind of dumb to lose to chicken.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,4,'Maybe you not notice, chicken move kind of fast.',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,5,'Time for more smart Dajik tip! If Goregek let chickens out again, make Goregek get chickens back again.',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,6,'I placed most of the spikes. Good amount of pointiness I think. You like?',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,7,'Oh! Dajik has idea! Make chicken sounds and maybe they come to you!',12,0,13,0,0,0,'Dajik'), +(@DAJIK,1,0,'Get the stuff off of body! Dajik hate it when he go skin something and there stuff in the way. So annoying.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,1,'Did you see face? Looked so scared, "Ah, big thing going to smash me!" Hah.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,2,'Hah! Maybe you learn a little after all!',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,3,'Yes! Stab few more time just in case! Stab good!',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,4,'Not sure how thing got here. Not matter if dead though',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,0,'We came for something, yes? Can''t remember.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,1,'Make sure you not forget anything! I forgot stuff once.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,2,'Dajik not think he seen you eat anything. You eat sometimes, yeah?',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,3,'I was going to draw picture of best attack plan... but you have my chalk.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,4,'Time for more smart Dajik tip! Make sure thing dead before reach in mouth for loots.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,0,'Seem like there more wasps every time Dajik come back. Why they not run out?',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,1,'Time for more smart Dajik tip! Try not to catch stinger with face. Not work so much.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,2,'In case you wonder, wasp sting not feel so good. No need to try.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,3,'Drone things not as tough as they look. Wasp things a bit nastier.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,4,'Try not to catch stinger with face. Not work so much.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,4,0,'No! You killed the queen thing! What have you... wait, nevermind. Sorry, that okay.',12,0,100,0,7000,0,'Dajik'), +(@DAJIK,5,0,'Dajik''s last learner eaten by sand-thing. We do better this time though!',12,0,100,0,0,0,'Dajik'), +(@DAJIK,6,0,'This not first queen slain by Frenzyheart. Seem like there always more.',12,0,100,0,0,0,'Dajik'), +(@DAJIK,7,0,'Sometimes big-tongues try to come get crystals. Not now because they not like it when we kill them.',12,0,34,0,0,0,'Dajik'), +(@DAJIK,7,1,'Time for more smart Dajik tip! Crystals work little too good for back scratch. No try.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,7,2,'Something big make pillars and crystals and everything. Frenzyheart not care much cause it not here anymore.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,8,0,'If you here to poke more softnuckles, Dajik going to poke you too.That a bad Goregek habit.',12,0,50,0,0,0,'Dajik'), +(@DAJIK,8,1,'Huh... where are we? This not right. I not tell you find hardknuckles, did I?',12,0,50,0,0,0,'Dajik'), +(@DAJIK,9,0,'Time for more smart Dajik tip! Lot of dead things mean lot of chance of being dead thing. Dajik leaving now.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,9,1,'Dead thing there already learn lesson of broken pillar. Leave this lesson for dumb, dead things. Going home now.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,9,2,'You all done with learning! Yup! All done! Dajik leave you and evil red pillar thing now.',12,0,34,0,0,0,'Dajik'), +(@ZEPIK,0,0,'Bring back good meat and the camp treat you like high-shaman for a day. Good deal.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,1,'Elder Harkek pretty good Frenzyheart. He help me a lot when I was littler and not liking Dajik.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,2,'I not in a big hurry. We can rest here a while if want.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,3,'I not live here always... I traveled lot of world on my own not long ago. I like all the stories of beasts and dragons and gods and stuff.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,4,'You should go let chickens out again and say Goregek did it. Never get old.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,1,0,'Hahah! You see that? Lightning bolt hit him right in the head!',12,0,33,0,0,0,'Zepik'), +(@ZEPIK,1,1,'Good one! It not even see it coming.',12,0,33,0,0,0,'Zepik'), +(@ZEPIK,1,2,'No more play?',12,0,34,0,0,0,'Zepik'), +(@ZEPIK,2,0,'You ever fought big dragon or god or anything? Zepik like hearing stories.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,1,'You pretty good! Natural at hunt, like me.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,2,'Goregek think he the boss of everyone, but he eat too much and hunt too little.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,3,'Bring back good meat and the camp treat you like high-shaman for a day. Good deal.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,4,'Dajik forget what he doing, where he at... sometime even forget his own name. Make him not so good teacher sometimes.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,5,'Elder Harkek pretty good Frenzyheart. He help me a lot when I was littler and not liking Dajik.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,6,'I think one reason I like hunting big-tongues so much... they not as dumb as the other hunts. They give a real fight.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,7,'Dajik tried to show me ways of hunt, but I do better when I do things my way.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,3,0,'Eat it big-tongues!',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,1,'Hah! Leave some for Zepik too.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,2,'That lake near here actually full of sea things. Not sure how it all get here... maybe in floods?',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,3,'I think one reason I like hunting big-tongues so much... they not as dumb as the other hunts. They give a real fight.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,4,'Mist big-tongues are smart with their shrine thing sometimes... cover whole area with mist and it get hard to find any.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,5,'Hah! This the fun part!',12,0,15,0,0,0,'Zepik'), +(@ZEPIK,3,6,'Flame! Death! Destruction! The black fire rages within my heart! I must... release it! Hahah!',12,0,15,0,0,0,'Zepik'), +(@ZEPIK,4,0,'Trust me - you going love this!',12,0,100,0,0,0,'Zepik'), +(@ZEPIK,5,0,'BOOM! That so good! More! More!',12,0,100,0,0,0,'Zepik'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9678 AND `SourceEntry`=13137; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (@FRENZYAURA,@RAINSPEAKERAURA,@WOLVARPING,@GORLOCPING,@DESSAWNRETAINER,@TREASUREPING,@DIGGINGFORTEASURE,@MOSSWALKERAURA,@SPEARBORNAURA,@MISTWHISPERAURA,@SAPPHIREHIVEAURA,@SKYREACHPILLARAURA); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,7,@FRENZYAURA,0,31,@GOREGEK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Goregek the Bristlepine Hunter'), +(13,7,@FRENZYAURA,1,31,@DAJIK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Dajik the Wasp Hunter'), +(13,7,@FRENZYAURA,2,31,@ZEPIK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Zepik the Gorloc Hunter'), +(13,7,@RAINSPEAKERAURA,0,31,@LAFOO,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Lafoo'), +(13,7,@RAINSPEAKERAURA,1,31,@MOODLE,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Jaloot'), +(13,7,@RAINSPEAKERAURA,2,31,@JALOOT,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Moodle'), +(13,7,@WOLVARPING,0,31,@GOREGEK,0,0,0,0,'','Spell Wolvar Location Ping targets Goregek the Bristlepine Hunter'), +(13,7,@WOLVARPING,1,31,@DAJIK,0,0,0,0,'','Spell Wolvar Location Ping targets Dajik the Wasp Hunter'), +(13,7,@WOLVARPING,2,31,@ZEPIK,0,0,0,0,'','Spell Wolvar Location Ping targets Zepik the Gorloc Hunter'), +(13,7,@GORLOCPING,0,31,@LAFOO,0,0,0,0,'','Spell Gorloc Location Ping targets Lafoo'), +(13,7,@GORLOCPING,1,31,@JALOOT,0,0,0,0,'','Spell Gorloc Location Ping targets Jaloot'), +(13,7,@GORLOCPING,2,31,@MOODLE,0,0,0,0,'','Spell Gorloc Location Ping targets Moodle'), +(13,7,@DESSAWNRETAINER,0,31,@LAFOO,0,0,0,0,'','Spell Dessawn Retainer targets Lafoo'), +(13,7,@DESSAWNRETAINER,1,31,@DAJIK,0,0,0,0,'','Spell Dessawn Retainer targets Dajik the Wasp Hunter'), +(13,7,@DESSAWNRETAINER,2,31,@ZEPIK,0,0,0,0,'','Spell Dessawn Retainer targets Zepik the Gorloc Hunter'), +(13,7,@DESSAWNRETAINER,3,31,@JALOOT,0,0,0,0,'','Spell Dessawn Retainer targets Jaloot '), +(13,7,@DESSAWNRETAINER,4,31,@MOODLE,0,0,0,0,'','Spell Dessawn Retainer targets Moodle'), +(13,7,@DESSAWNRETAINER,5,31,@GOREGEK,0,0,0,0,'','Spell Dessawn Retainer targets Goregek'), +(13,7,@TREASUREPING,0,31,@LAFOO,0,0,0,0,'','Spell Dessawn Retainer targets Lafoo'), +(13,7,@TREASUREPING,1,31,@JALOOT,0,0,0,0,'','Spell Dessawn Retainer targets Jaloot '), +(13,7,@TREASUREPING,2,31,@MOODLE,0,0,0,0,'','Spell Dessawn Retainer targets Moodle'), +(13,7,@DIGGINGFORTEASURE,0,31,@GLINTINGDIRT,0,0,0,0,'','digging for treasure targets glinting dirt'), +(13,7,@MOSSWALKERAURA,0,31,@MOODLE,0,0,0,0,'','Mosswalker village aura targets moodle'), +(13,7,@SPEARBORNAURA,0,31,@JALOOT,0,0,0,0,'','spearborn encampment aura targets moodle'), +(13,7,@MISTWHISPERAURA,0,31,@ZEPIK,0,0,0,0,'','mistwhisper refuge aura targets zepik'), +(13,7,@SAPPHIREHIVEAURA,0,31,@DAJIK,0,0,0,0,'','sapphire hive aura targets dajik'), +(13,7,@SKYREACHPILLARAURA,0,31,@DAJIK,0,0,0,0,'','skyreach pillar aura targets dajik'), +(14,9678,13137,0,5,1104,7,0,0,0,'','Shaman Vekjik - Show different gossip if player is hated, hostile or unfriendly with Frenzyheart Tribe'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN(@GLINTINGDIRT,@LAFOO,@JALOOT,@MOODLE,@GOREGEK,@DAJIK,@ZEPIK,@MOSSWALKERBUNNY) AND `SourceId`=0; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(22,1,@LAFOO,0,0,9,0,12704,0,0,0,0,'','Lafoo SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@LAFOO,0,0,29,0,@GLINTINGDIRT,10,0,0,0,'','Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@LAFOO,0,1,9,0,12572,0,0,0,0,'','Lafoo SAI only activates if player is on and has not completed the Gods like shiny things'), +(22,1,@LAFOO,0,1,29,0,@GLINTINGDIRT,10,0,0,0,'','Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@JALOOT,0,0,9,0,12704,0,0,0,0,'','Jaloot SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@JALOOT,0,0,29,0,@GLINTINGDIRT,10,0,0,0,'','Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@MOODLE,0,0,9,0,12704,0,0,0,0,'','Moodle SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@MOODLE,0,0,29,0,@GLINTINGDIRT,10,0,0,0,'','Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@GLINTINGDIRT,0,0,29,1,@LAFOO,5,0,0,0,'','Execute SAI only if Lafoo within 2 yards'), +(22,1,@GLINTINGDIRT,0,1,29,1,@JALOOT,5,0,0,0,'','Execute SAI only if Jaloot within 2 yards'), +(22,1,@GLINTINGDIRT,0,2,29,1,@MOODLE,5,0,0,0,'','Execute SAI only if Moodle within 2 yards'), +(22,13,@MOODLE,0,0,23,1,4297,0,0,1,0,'','Moodle dont execute SAI in Mosswalker Village'), +(22,9,@GOREGEK,0,0,23,1,4303,0,0,1,0,'','Goregek dont execute SAI in Hardknuckle Clearing'), +(22,10,@ZEPIK,0,0,23,1,4306,0,0,1,0,'','Zepik dont execute SAI in Mistwhisper Refuge'), +(22,12,@GOREGEK,0,0,23,1,4303,0,0,0,0,'','Goregek execute SAI in only in Hardknuckle Clearing'), +(22,9,@DAJIK,0,0,23,1,4304,0,0,1,0,'','Dajik Dont execute SAI in Sapphire Hive'), +(22,9,@DAJIK,0,0,23,1,4303,0,0,1,0,'','Dajik execute SAI in Hardknuckle Clearing'), +(22,9,@DAJIK,0,0,23,1,4388,0,0,1,0,'','Dajik execute SAI in Wintergrasp River'), +(22,9,@DAJIK,0,0,23,1,4295,0,0,1,0,'','Dajik execute SAI in The Sundered Shard'), +(22,19,@DAJIK,0,0,23,1,4303,0,0,0,0,'','Dajik execute SAI only in Hardknuckle Clearing'), +(22,11,@LAFOO,0,0,23,1,4291,0,0,1,0,'','Lafoo dont execute sai in rainspeaker canopy'), +(22,13,@JALOOT,0,0,23,1,4291,0,0,1,0,'','Jaloot dont execute sai in rainspeaker canopy'), +(22,13,@JALOOT,0,1,23,1,4308,0,0,1,0,'','Jaloot dont execute sai in spearborn encampment'), +(22,13,@MOODLE,0,0,23,1,4291,0,0,1,0,'','Moodle dont execute sai in rainspeaker canopy'), +(22,9,@GOREGEK,0,0,23,1,4292,0,0,1,0,'','Goregek dont execute sai in frenzyheart hill'), +(22,9,@DAJIK,0,0,23,1,4292,0,0,1,0,'','Dajik dont execute sai in frenzyheart hill'), +(22,10,@ZEPIK,0,0,23,1,4292,0,0,1,0,'','Zepik dont execute sai in frenzyheart hill'), +(22,2,@MOSSWALKERBUNNY,0,0,1,0,@SHOLAZARGUARDIANHEARTBEAT,0,0,0,0,'','Mosswalker Bunny execute SAI only if player has sholazar guardian heartbeat aura'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @HARDKNUCKLEMATRIARCH; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@HARDKNUCKLEMATRIARCH; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@HARDKNUCKLEMATRIARCH; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@HARDKNUCKLEMATRIARCH, 0, 0, 1, 4, 0, 100, 0, 0, 0, 0, 0, 11, 54287, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - On Agro - Cast Enrage'), +(@HARDKNUCKLEMATRIARCH, 0, 1, 0,61, 0, 100, 0, 0, 0, 0, 0, 1 , 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - Linked with Previous Event - Say'), +(@HARDKNUCKLEMATRIARCH, 0, 2, 0, 0, 0, 100, 0, 6000, 10000, 12000, 15000, 11 , 61580, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - In Combat - Cast Cast Thunderstomp'), +(@HARDKNUCKLEMATRIARCH, 0, 3, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, @GOREGEK, 0, 50, 0, 0, 0, 0, 'Hardknuckle Matriarch - On Death Send Data to Goregek'); + +DELETE FROM `creature_ai_texts` WHERE `entry`= -738; +DELETE FROM `creature_text` WHERE `entry`=@HARDKNUCKLEMATRIARCH; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@HARDKNUCKLEMATRIARCH, 0, 0, 'We are Not Amused', 12, 0, 100, 0, 0, 0, 'Hardknuckle Matriarch'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @SAPPHIREQUEEN; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@SAPPHIREQUEEN; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@SAPPHIREQUEEN; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@SAPPHIREQUEEN, 0, 0, 0, 0, 0, 100, 0, 6000, 9000, 9000, 14000, 11, 48193, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Sapphire Hive Queen - IC - Cast Poison Stinger'), +(@SAPPHIREQUEEN, 0, 1, 0, 2, 0, 100, 0, 0, 30, 12000, 15000, 11, 54761, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Sapphire Hive Queen - On 30% Hp - Cast Enrage'), +(@SAPPHIREQUEEN, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, @DAJIK, 0, 50, 0, 0, 0, 0, 'Sapphire Hive Queen - On Death - Set Data Dajik'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @VENOMTIP; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@VENOMTIP; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@VENOMTIP; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@VENOMTIP, 0, 0, 0, 0, 0, 100, 0, 7000, 9000, 17000, 20000, 11, 61550, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Venomtip - IC - Cast Cobra Strike'), +(@VENOMTIP, 0, 1, 0, 9, 0, 100, 0, 0, 30, 7000, 12000, 11, 32330, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Venomtip - On Range - Cast Poison Spit'), +(@VENOMTIP, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 9, @LAFOO, 0, 50, 0, 0, 0, 0, 'Venomtip - On Death - Set Data Lafoo'); diff --git a/sql/updates/world/2013_04_05_00_world_sai.sql b/sql/updates/world/2013_04_05_00_world_sai.sql new file mode 100644 index 00000000000..4e304843d4f --- /dev/null +++ b/sql/updates/world/2013_04_05_00_world_sai.sql @@ -0,0 +1,927 @@ +SET @HO_SOOSAY := 28027; +SET @HO_GOSSIP := 9742; +SET @O_STATE := 50503; +SET @T_STORM := 53071; +SET @FI_LAFOO := 52547; +SET @FI_JALOOT := 52548; +SET @FI_MOODLE := 52549; +SET @SEEINVIS := 52214; +SET @RAINSPEAKERAURA := 51639; +SET @TREASUREPING := 51420; +SET @GORLOCPING := 51794; +SET @WOLVARPING := 51791; +SET @DIGUPGLINTINGBUG := 51443; +SET @DIGUPSPARKINGHARE := 51441; +SET @DIGUPSHININGCRYSTAL := 51397; +SET @DIGUPGLINTINGARMOR := 51398; +SET @DIGUPGLOWINGGEM := 51400; +SET @DIGUPPOLISHEDPLATTER := 51401; +SET @DIGUPSPARKINGTREASURE := 51402; +SET @BLESSINGOFTHESPARKINGHARE := 51442; +SET @JALOOTSINTENSITY := 52119; +SET @RAINSPEAKERBUNNY := 28455; +SET @LAFOO := 28120; +SET @MOODLE := 28122; +SET @JALOOT := 28121; +SET @GLINTINGDIRT := 28362; +SET @GLINTINGBUG := 28372; +SET @SPARKLINGHARE := 28371; +SET @GLINTINGDIRTSCRIPT := 2836201; +SET @GORLOCTREASURESCRIPT := 2812000; +SET @ELDER_HARKEK := 28138; +SET @SHAMAN_RAKJAK := 28082; +SET @EH_GOSSIP := 9741; +SET @FRENZYAURA := 51234; +SET @FRENZYBUNNY := 28299; +SET @GOREGEK := 28214; +SET @DAJIK := 28215; +SET @ZEPIK := 28216; +SET @FI_GOREGEK := 52542; +SET @FI_DAJIK := 52544; +SET @FI_ZEPIK := 52545; +SET @CHICKENSEEINVIS := 50735; +SET @DESSAWNRETAINER := 53163; +SET @MOSSWALKERAURA := 51644; +SET @MOSSWALKERBUNNY := 28459; +SET @ANGRYGORLOCCREDIT := 54057; +SET @MISTWHISPERAURA := 51239; +SET @MISTWHISPERBUNNY := 28300; +SET @SPEARBORNAURA := 51642; +SET @SPEARBORNBUNNY := 28457; +SET @KARTAKHOLDAURA := 51643; +SET @KARTAKHOLDBUNNY := 28458; +SET @SPARKTOUCHEDAURA := 51641; +SET @SPARKTOUCHEDBUNNY := 28456; +SET @SAPPHIREHIVEAURA := 51651; +SET @LIFEBLOODPILLARBUNNY := 28460; +SET @LIFEBLOODPILLARAURA:= 51649; +SET @SKYREACHPILLARBUNNY := 28454; +SET @SKYREACHPILLARAURA:= 51645; +SET @SAPPHIREHIVEBUNNY := 28462; +SET @GORLOCLOCATIONPERIODIC := 51793; +SET @WOLVARLOCATIONPERIODIC := 51792; +SET @LOOKINGFORTREASUREAURA := 51407; +SET @SHOLAZARGUARDIANHEARTBEAT := 51623; +SET @DIGGINGFORTEASURE := 51405; +SET @GOREGEKSSHACKLE := 38619; +SET @DAJIKSCHALK := 38621; +SET @ZEPIKSHUNTINGHORN := 38512; +SET @LAFOOSBUGBAG := 38622; +SET @JALOOTSCRYSTAL := 38623; +SET @MOODLESSTRESSBALL := 38624; +SET @INVISIBILTY := 52213; +SET @CHICKENLOCATIONPING := 51843; +SET @CHICKENNET := 51959; +SET @CHICKENESCAPEE := 28161; +SET @HARDKNUCKLE := 28096; +SET @HARDKNUCKLEMATRIARCH := 28213; +SET @SOFTKNUCKLE := 28127; +SET @SAPPHIREQUEEN := 28087; +SET @VENOMTIP := 28358; +SET @SERFEXTHEREAVER := 28083; +SET @MISTWHISPERLIGHTNINGCLOUD := 28253; +SET @MISTWHISPERLIGHTNINGTARGET := 28254; +SET @ARRANGEDCRYSTALFORMATIONBUNNY := 28273; +SET @SCAREDSOFTKNUCKLE := 50979; +SET @PITCH := 28097; +SET @TRACKERGEKGEK := 28095; +SET @MOSSWALKERVICTIM := 28113; + +SET @GOBJGUID := 4598; -- Needs 2 gobject guids for Lightning Definitly strikes twice, one for spellfocus, other for arranged crystal formation since cant find spell to spawn this, +SET @QUESTPOOL := 359; -- Needs 4, 2 for oracles and 2 for frenzyheart, + +UPDATE `creature_template` SET `unit_class`=2 WHERE `entry` IN(@DAJIK,@ZEPIK); +UPDATE `creature_template` SET `minlevel`=77, `maxlevel`=77, `exp`=2,`mindmg`=371, `maxdmg`=522,`attackpower`=478 WHERE `entry`IN (@GOREGEK,@DAJIK,@ZEPIK); +UPDATE `creature_template` SET `unit_flags` =33555200 WHERE `entry`IN (@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry` IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK); +DELETE FROM `creature_ai_scripts` WHERE `creature_id`IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK); +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(@HO_SOOSAY,@ELDER_HARKEK,@SHAMAN_RAKJAK); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@HO_SOOSAY,0,0,0,1,0,100,0,0,0,0,0,75,@O_STATE,0,0,0,0,0,1,0,0,0,0,0,0,0, 'High-Oracle Soo-say - Out of combat - Add Oracle State Aura'), +(@HO_SOOSAY,0,1,0,0,0,100,0,5000,10000,12000,16000,11,@T_STORM,0,0,0,0,0,2,0,0,0,0,0,0,0, 'High-Oracle Soo-say - In Combat - Cast Thunderstorm'), +(@HO_SOOSAY,0,2,8,62,0,100,0,@HO_GOSSIP,0,0,0,85,@FI_LAFOO,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Lafoo'), +(@HO_SOOSAY,0,3,8,62,0,100,0,@HO_GOSSIP,1,0,0,85,@FI_LAFOO,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Lafoo'), +(@HO_SOOSAY,0,4,8,62,0,100,0,@HO_GOSSIP,2,0,0,85,@FI_JALOOT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Jaloot'), +(@HO_SOOSAY,0,5,8,62,0,100,0,@HO_GOSSIP,3,0,0,85,@FI_JALOOT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Jaloot'), +(@HO_SOOSAY,0,6,8,62,0,100,0,@HO_GOSSIP,4,0,0,85,@FI_MOODLE,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Moodle'), +(@HO_SOOSAY,0,7,8,62,0,100,0,@HO_GOSSIP,5,0,0,85,@FI_MOODLE,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Spellcast Forceitem Moodle'), +(@HO_SOOSAY,0,8,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On gossip select - Close gossip'), +(@HO_SOOSAY,0,9,0,20,0,100,0,12704,0,0,0,28,@SEEINVIS,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Complete - Remove Aura Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY,0,10,0,19,0,100,0,12704,0,0,0,85,@SEEINVIS,2,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Accept - Invoker Cast Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY,0,11,0,20,0,100,0,12572,0,0,0,28,@SEEINVIS,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Complete - Remove Aura Rainspeaker Treasures: See Invisibility'), +(@HO_SOOSAY,0,12,0,19,0,100,0,12574,0,0,0,57,@LAFOOSBUGBAG,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Accept - Remove Lafoos Bug bag'), +(@HO_SOOSAY,0,13,0,20,0,100,0,12577,0,0,0,57,@JALOOTSCRYSTAL,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Complete - Remove Jaloots favourite crystal'), +(@HO_SOOSAY,0,14,0,20,0,100,0,12581,0,0,0,57,@MOODLESSTRESSBALL,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Oracle Soo-say - On Quest Complete - Remove Moodles Stress Ball'), +(@SHAMAN_RAKJAK,0,0,0,19,0,100,0,12529,0,0,0,11,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Goregek'), +(@SHAMAN_RAKJAK,0,1,0,19,0,100,0,12530,0,0,0,11,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Goregek'), +(@SHAMAN_RAKJAK,0,2,0,19,0,100,0,12533,0,0,0,11,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Dajik'), +(@SHAMAN_RAKJAK,0,3,0,19,0,100,0,12534,0,0,0,11,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Dajik'), +(@SHAMAN_RAKJAK,0,4,0,19,0,100,0,12536,0,0,0,11,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On quest accept - Spellcast Forceitem Zepik'), +(@SHAMAN_RAKJAK,0,15,0,19,0,100,0,12533,0,0,0,57,@GOREGEKSSHACKLE,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On Quest Accept - Remove Goregeks Shackes'), +(@SHAMAN_RAKJAK,0,16,0,19,0,100,0,12536,0,0,0,57,@DAJIKSCHALK,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On Quest Accept - Remove Dajiks Chalk'), +(@SHAMAN_RAKJAK,0,17,0,19,0,100,0,12540,0,0,0,57,@ZEPIKSHUNTINGHORN,1,0,0,0,0,7,0,0,0,0,0,0,0, 'High-Shaman Rakjak - On Quest Accept - Remove Zepiks Hunting Horn'), +(@ELDER_HARKEK,0,4,10,62,0,100,0,@EH_GOSSIP,0,0,0,85,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Goregek'), +(@ELDER_HARKEK,0,5,10,62,0,100,0,@EH_GOSSIP,1,0,0,85,@FI_GOREGEK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Goregek'), +(@ELDER_HARKEK,0,6,10,62,0,100,0,@EH_GOSSIP,2,0,0,85,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Dajik'), +(@ELDER_HARKEK,0,7,10,62,0,100,0,@EH_GOSSIP,3,0,0,85,@FI_DAJIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Dajik'), +(@ELDER_HARKEK,0,8,10,62,0,100,0,@EH_GOSSIP,4,0,0,85,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Zepik'), +(@ELDER_HARKEK,0,9,10,62,0,100,0,@EH_GOSSIP,5,0,0,85,@FI_ZEPIK,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Spellcast Forceitem Zepik'), +(@ELDER_HARKEK,0,10,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On gossip select - Close gossip'), +(@ELDER_HARKEK,0,3,0,20,0,100,0,12702,0,0,0,28,@CHICKENSEEINVIS,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On Quest Complete - Remove Aura Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK,0,2,0,20,0,100,0,12532,0,0,0,28,@CHICKENSEEINVIS,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On Quest Complete - Remove Aura Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK,0,1,0,19,0,100,0,12702,0,0,0,85,@CHICKENSEEINVIS,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On Quest Accept - Invoker Cast Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK,0,0,0,19,0,100,0,12532,0,0,0,85,@CHICKENSEEINVIS,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On Quest Accept - Invoker Cast Frenzyheart Chicken: See Invisibility'), +(@ELDER_HARKEK,0,11,0,19,0,100,0,12534,0,0,0,57,@GOREGEKSSHACKLE,1,0,0,0,0,7,0,0,0,0,0,0,0, 'Elder Harkek - On Quest Accept - Remove Goregeks Shackes'); + +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN(@HO_GOSSIP,@EH_GOSSIP) AND `id` IN(0,1,2,3,4,5); +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(@HO_GOSSIP,0,0, 'I need to find Lafoo, do you have his bug bag?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,1,0, 'I need to find Lafoo, do you have his bug bag?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,2,0, 'I need to find Jaloot, do you have his favorite crystal?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,3,0, 'I need to find Jaloot, do you have his favorite crystal?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,4,0, 'I need to find Moodle, do you have his stress ball?',1,1,0,0,0,0, ''), +(@HO_GOSSIP,5,0, 'I need to find Moodle, do you have his stress ball?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,0,0, 'I need to find Goregek, do you have his shackles?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,1,0, 'I need to find Goregek, do you have his shackles?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,2,0, 'I need to find Dajik, do you have his chalk?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,3,0, 'I need to find Dajik, do you have his chalk?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,4,0, 'I need to find Zepik, do you have his hunting horn?',1,1,0,0,0,0, ''), +(@EH_GOSSIP,5,0, 'I need to find Zepik, do you have his hunting horn?',1,1,0,0,0,0, ''); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`IN(@HO_GOSSIP,@EH_GOSSIP); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@HO_GOSSIP,0,0,0,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,0,9,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,2,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,2,8,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,1,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,0,0,1,28,0,12571,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has completed Quest Make the Bad Snake go away'), +(15,@HO_GOSSIP,0,0,0,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,0,0,1,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,0,0,2,8,0,12573,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Making Peace'), +(15,@HO_GOSSIP,1,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,1,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,1,0,0,2,0,@LAFOOSBUGBAG,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Lafoo''s Bug Bag'), +(15,@HO_GOSSIP,4,0,0,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,0,9,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,2,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,2,8,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,1,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,1,28,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,0,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,1,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,2,8,0,12579,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest Lifeblood of the Mosswalker Shrine'), +(15,@HO_GOSSIP,4,0,3,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,3,9,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,5,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,5,8,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,4,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Moodle''s Stress Ball'), +(15,@HO_GOSSIP,4,0,4,28,0,12578,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Quest The Angry Gorloc'), +(15,@HO_GOSSIP,4,0,3,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,4,0,4,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,4,0,5,8,0,12580,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Quest The Mosswalker Savior'), +(15,@HO_GOSSIP,3,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,3,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,3,0,0,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Jaloot''s Favorite Crystal'), +(15,@HO_GOSSIP,2,0,0,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,0,9,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Taken Quest Back so soon?'), +(15,@HO_GOSSIP,2,0,2,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,2,8,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Rewarded Back so soon?'), +(15,@HO_GOSSIP,2,0,1,2,0,@JALOOTSCRYSTAL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player doesn''t already have Jaloot''s Favourite Crystal'), +(15,@HO_GOSSIP,2,0,1,28,0,12574,0,0,0,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has Completed Back so soon?'), +(15,@HO_GOSSIP,2,0,0,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,2,0,1,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,2,0,2,8,0,12577,0,0,1,0,0, '', 'High-Oracle Soo-say - Show Gossip if player Has not completed Home Time'), +(15,@HO_GOSSIP,5,0,0,8,0,12695,0,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has rewarded quest Return of the Friendly Dryskin'), +(15,@HO_GOSSIP,5,0,0,5,0,1105,224,0,0,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player is at least honored with The Oracles'), +(15,@HO_GOSSIP,5,0,0,2,0,@MOODLESSTRESSBALL,1,0,1,0,0, '', 'High-Oracle Soo-say - Show gossip option only if player has no item Moodle''s Stress Ball'), +(15,@EH_GOSSIP,0,0,0,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,0,9,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,2,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,2,8,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,1,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,1,28,0,12529,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Ape Hunters Slave'), +(15,@EH_GOSSIP,0,0,3,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,3,9,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,4,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,4,8,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,5,2,0,@GOREGEKSSHACKLE,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Gorekeks Shackles'), +(15,@EH_GOSSIP,0,0,5,28,0,12530,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest Tormenting the Softknuckles'), +(15,@EH_GOSSIP,0,0,0,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,1,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,2,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,3,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,4,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,5,14,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,0,0,0,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,1,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,2,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,3,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,4,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,0,0,5,14,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest The Underground Menace '), +(15,@EH_GOSSIP,2,0,0,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,0,9,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,2,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,2,8,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,1,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,1,28,0,12533,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Wasp Hunters Apprentice'), +(15,@EH_GOSSIP,2,0,3,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,3,9,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,4,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,4,8,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,5,2,0,@DAJIKSCHALK,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Dajiks Worn Chalk'), +(15,@EH_GOSSIP,2,0,5,28,0,12534,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest The Underground Menace'), +(15,@EH_GOSSIP,2,0,0,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,1,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,2,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,3,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,4,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,2,0,5,14,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,0,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,0,9,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Taken Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,2,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,2,8,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has Rewarded Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,1,2,0,@ZEPIKSHUNTINGHORN,1,1,1,0,0, '', 'Elder Harkek - Show Gossip if player doesn''t already have Zepiks Hunting Horn'), +(15,@EH_GOSSIP,4,0,1,28,0,12536,0,0,0,0,0, '', 'Elder Harkek - Show Gossip if player Has completed Quest A Rough Ride'), +(15,@EH_GOSSIP,4,0,0,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'), +(15,@EH_GOSSIP,4,0,1,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'), +(15,@EH_GOSSIP,4,0,2,8,0,12539,0,0,1,0,0, '', 'Elder Harkek - Show Gossip if player Has not completed Quest Hoofing It'); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@EH_GOSSIP,1,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15,@EH_GOSSIP,1,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15,@EH_GOSSIP,1,0,2,@GOREGEKSSHACKLE,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Goregek''s Shackles'), +(15,@EH_GOSSIP,3,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15,@EH_GOSSIP,3,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15,@EH_GOSSIP,3,0,2,@DAJIKSCHALK,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Dajiks Worn Chalk'), +(15,@EH_GOSSIP,5,0,8,12692,0,0,0,0, '', 'Elder Harkek - Show gossip option only if player has rewarded quest Return of the Lich Hunter'), +(15,@EH_GOSSIP,5,0,5,1104,224,0,0,0, '', 'Elder Harkek - Show gossip option only if player is at least honored with Frenzheart Tribe'), +(15,@EH_GOSSIP,5,0,2,@ZEPIKSHUNTINGHORN,1,0,1,0, '', 'Elder Harkek - Show gossip option only if player has no item Zepiks Hunting Horn'); +-- Jaloot's Itensity and Blessing of the Sparkling Hare don't stack +DELETE FROM `spell_group` WHERE `id`=@BLESSINGOFTHESPARKINGHARE; +INSERT INTO `spell_group` (`id`,`spell_id`) VALUES +(@BLESSINGOFTHESPARKINGHARE,@BLESSINGOFTHESPARKINGHARE), +(@BLESSINGOFTHESPARKINGHARE,@JALOOTSINTENSITY); + +DELETE FROM `spell_group_stack_rules` WHERE `group_id`=@BLESSINGOFTHESPARKINGHARE; +INSERT INTO `spell_group_stack_rules` (`group_id`,`stack_rule`) VALUES +(@BLESSINGOFTHESPARKINGHARE,1); + +DELETE FROM `creature_template_addon` WHERE `entry`IN(@GLINTINGDIRT,@LAFOO,@JALOOT,@MOODLE,@GLINTINGBUG,@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(@GLINTINGBUG, 0, 0, 0, 1, 0, '51444'), +(@GOREGEK, 0, 0, 0, 1, 0,'54178'), +(@DAJIK, 0, 0, 0, 1, 0,'52734'), +(@ZEPIK, 0, 0, 0, 1, 0,'54176'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=@SEEINVIS AND `spell_effect`=@LOOKINGFORTREASUREAURA; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(@SEEINVIS, @LOOKINGFORTREASUREAURA, 2, 'Looking for treasure aura triggered by Rainspeaker Treasures: See Invisibility'); + +DELETE FROM `spell_area` WHERE `spell`=@SEEINVIS; +DELETE FROM `spell_area` WHERE `spell`=@ANGRYGORLOCCREDIT; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@GLINTINGDIRT; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@GLINTINGDIRT; +DELETE FROM `smart_scripts` WHERE `entryorguid` BETWEEN @GLINTINGDIRTSCRIPT AND @GLINTINGDIRTSCRIPT+5; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@GLINTINGDIRT,0,0 ,0,38, 0,100,1,1,1,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - On Data Set - Increment Phase'), +(@GLINTINGDIRT,0,1 ,0,1, 1,100,1,0,0,0,0,87,@GLINTINGDIRTSCRIPT,@GLINTINGDIRTSCRIPT+1,@GLINTINGDIRTSCRIPT+2,@GLINTINGDIRTSCRIPT+3,@GLINTINGDIRTSCRIPT+4,@GLINTINGDIRTSCRIPT+5,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Run Random Script'), +(@GLINTINGDIRT,0,2 ,0,1, 1,40,1,100,300,3500,3500,11,@DIGUPGLINTINGBUG,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Cast Dig up Glinting Bug'), +(@GLINTINGDIRT,0,3 ,0,1, 1,40,1,100,300,3500,3500,11,@DIGUPGLINTINGBUG,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Cast Dig up Glinting Bug'), +(@GLINTINGDIRT,0,4 ,0,1, 1,40,1,100,300,3500,3500,11,@DIGUPGLINTINGBUG,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Cast Dig up Glinting Bug'), +(@GLINTINGDIRT,0,5 ,0,1, 1,100,1,400,400,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - OOC (Phase 2) - Despawn'), +(@GLINTINGDIRT,0,6 ,0,11, 0,100,0,0,0,0,0,11,@INVISIBILTY,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - On Spawn - Cast Rainspeaker Treasures: Invisibility'), +(@GLINTINGDIRTSCRIPT,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSPARKINGHARE,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Sparking Hare'), +(@GLINTINGDIRTSCRIPT,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+1,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSHININGCRYSTAL,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Shining Crystal'), +(@GLINTINGDIRTSCRIPT+1,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+2,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPGLINTINGARMOR,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Glinting Armor'), +(@GLINTINGDIRTSCRIPT+2,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+3,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPGLOWINGGEM,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Glowing Gem'), +(@GLINTINGDIRTSCRIPT+3,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+4,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPPOLISHEDPLATTER,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Polished Platter'), +(@GLINTINGDIRTSCRIPT+4,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'), +(@GLINTINGDIRTSCRIPT+5,9,0 ,0,0, 0,100,0,5000,5000,0,0,11,@DIGUPSPARKINGTREASURE,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Cast Dig Up Sparking Treasure'), +(@GLINTINGDIRTSCRIPT+5,9,1 ,0,0, 0,100,0,5500,5500,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Dirt - Script - Despawn'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN(@RAINSPEAKERBUNNY,@FRENZYBUNNY,@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +UPDATE `creature_template` SET `AIName`= 'SmartAI',`unit_flags`=32776,`InhabitType`=3 WHERE `entry`In(@LAFOO,@MOODLE,@JALOOT,@GOREGEK,@DAJIK,@ZEPIK); +UPDATE `creature_template` SET `gossip_menu_id`=9747, `npcflag`=`npcflag`|1, `speed_run`=1.30952 WHERE `entry`=@JALOOT; +UPDATE `creature_template` SET `npcflag`=`npcflag`|1, `speed_run`=1.19048 WHERE `entry`=@MOODLE; +UPDATE `gossip_menu_option` SET `action_menu_id`=9684 WHERE `menu_id`=9677; +UPDATE `creature_template` SET `gossip_menu_id`=9745 WHERE `entry`=28106; +UPDATE `creature_template` SET `speed_walk`=0.66667, `speed_run`=0.99206 WHERE `entry`=@GOREGEK; +UPDATE `creature_template` SET `speed_walk`=0.66667, `speed_run`=0.99206, `npcflag`=`npcflag`|1 WHERE `entry`=@ZEPIK; +UPDATE `gossip_menu_option` SET `action_menu_id`=9684 WHERE `menu_id`=9677; +DELETE FROM `creature_involvedrelation` WHERE `id`=28216 AND `quest`=12582; + +DELETE FROM `gossip_menu` WHERE `entry`=9747; +DELETE FROM `gossip_menu` WHERE `entry`=9562 AND `text_id`=12883; +DELETE FROM `gossip_menu` WHERE `entry`=9570 AND `text_id`=12905; +DELETE FROM `gossip_menu` WHERE `entry`=9678 AND `text_id`=13136; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9562,12883), +(9570,12905), +(9678,13136), +(9747,13367); + +DELETE FROM `npc_text` WHERE `ID`=13136; +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(13136,'Vekjik no want to be bothered.','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340); + +DELETE FROM `creature_equip_template` WHERE `entry` IN (@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_equip_template` (`entry`,`id`,`itemEntry1`,`itemEntry2`,`itemEntry3`) VALUES +(@GOREGEK,1,36488,0,0), +(@DAJIK,1,28325,0,0), +(@ZEPIK,1,28914,0,5258); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(@LAFOO,@MOODLE,@JALOOT,@GOREGEK,@DAJIK,@ZEPIK,@GORLOCTREASURESCRIPT,@RAINSPEAKERBUNNY,@FRENZYBUNNY,@MOSSWALKERBUNNY,@MISTWHISPERBUNNY,@SPEARBORNBUNNY,@KARTAKHOLDBUNNY,@SPARKTOUCHEDBUNNY,@SAPPHIREHIVEBUNNY,@LIFEBLOODPILLARBUNNY,@SKYREACHPILLARBUNNY); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@GOREGEK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Set React State'), +(@GOREGEK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Say line'), +(@GOREGEK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Despawn'), +(@GOREGEK,0,3,0,0,0,100,0,3000,6000,8000,16000,11,54188,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Goregek - IC - Cast Sunder Armor'), +(@GOREGEK,0,4,0,0,0,100,0,5000,8000,15000,20000,11,52743,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Goregek - IC - Cast Head Smack'), +(@GOREGEK,0,5,0,2,0,100,0,0,30,60000,60000,11,52748,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Less than 30% HP - Cast Voracious Appetite'), +(@GOREGEK,0,6,0,13,0,100,0,12000,20000,0,0,11,6713,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Target Casting - Cast Disarm'), +(@GOREGEK,0,7 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Creature Death - Say'), +(@GOREGEK,0,8 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Gorekek - OOC - Say'), +(@GOREGEK,0,9 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Cast Wolvar Location Periodic'), +(@GOREGEK,0,10 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@GOREGEK,0,11 ,0,1,0,100,0,10000,40000,45000,90000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Gorekek - OOC - Say'), +(@GOREGEK,0,12 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - OOC - Set Phase 2'), +(@GOREGEK,0,13 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Agro - Set Phase 1'), +(@GOREGEK,0,14 ,0,38,0,100,0,1,1,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On Data Set - Say'), +(@GOREGEK,0,15,0,8,2,100,0,@KARTAKHOLDAURA,0,40000,70000,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - On spellhit - Say line'), +(@GOREGEK,0,16,0,8,2,100,0,@CHICKENLOCATIONPING,0,6000,10000,11,@CHICKENNET,0,0,0,0,0,19,@CHICKENESCAPEE,5,0,0,0,0,0, 'Goregek - On spellhit - Cast Chicken Net'), +(@DAJIK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Spawn - Set React State'), +(@DAJIK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Despawn'), +(@DAJIK,0,3,0,0,0,100,0,3000,6000,8000,12000,11,54195,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Dajik - IC - Cast Earth''s Wrath'), +(@DAJIK,0,4,0,0,0,100,0,5000,8000,15000,20000,11,54193,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Dajik - IC - Cast Earth''s Fury'), +(@DAJIK,0,5,0,2,0,100,0,0,30,60000,60000,11,54206,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Less than 30% HP - Cast Mend'), +(@DAJIK,0,6 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death - Say'), +(@DAJIK,0,8 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Say'), +(@DAJIK,0,9,0,8,2,100,0,@SAPPHIREHIVEAURA,0,40000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,10 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Spawn - Cast Wolvar Location Periodic'), +(@DAJIK,0,11 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik -Goregek - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@DAJIK,0,12 ,0,38,0,100,0,1,1,0,0,1,4,5000,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death (Sapphire Queen) - Say'), +(@DAJIK,0,13 ,0,38,0,100,0,1,2,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Creature Death (Serfex the Reaver) - Say'), +(@DAJIK,0,14 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Set Phase 2'), +(@DAJIK,0,15 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On Agro - Set Phase 1'), +(@DAJIK,0,16 ,0,52,0,100,0,4,@DAJIK,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik On - Text Over - Say'), +(@DAJIK,0,17,0,8,2,100,0,@SKYREACHPILLARAURA,0,40000,70000,1,7,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,18 ,0,1,0,100,0,10000,40000,45000,90000,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - OOC - Say'), +(@DAJIK,0,19,0,8,2,100,0,@LIFEBLOODPILLARAURA,0,40000,70000,1,9,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Dajik - On spellhit - Say line'), +(@DAJIK,0,20,0,8,2,100,0,@CHICKENLOCATIONPING,0,6000,10000,11,@CHICKENNET,0,0,0,0,0,19,@CHICKENESCAPEE,5,0,0,0,0,0, 'Dajik - On spellhit - Cast Chicken Net'), +(@ZEPIK,0,0 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Set React State'), +(@ZEPIK,0,1,0,8,0,100,0,@FRENZYAURA,0,45000,70000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Say line'), +(@ZEPIK,0,2,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Despawn'), +(@ZEPIK,0,3,0,0,0,100,0,4000,7000,15000,18000,11,52761,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Barbed Net'), +(@ZEPIK,0,4,0,0,0,100,0,5000,8000,12000,15000,11,52889,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Envenomed Shot'), +(@ZEPIK,0,5,0,0,0,100,0,0,6000,15000,18000,11,52873,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Open Wound'), +(@ZEPIK,0,6,0,0,0,100,0,3000,5000,3000,7000,11,52758,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - IC - Cast Piercing Arrow'), +(@ZEPIK,0,7,0,2,0,100,0,0,30,60000,60000,11,52895,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik the Gorloc Hunter - On Less than 30% HP Cast Bandage - Cast Bandage'), +(@ZEPIK,0,8 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Creature Death - Say'), +(@ZEPIK,0,9 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - OOC - Say'), +(@ZEPIK,0,10,0,8,2,100,0,@MISTWHISPERAURA,0,40000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On spellhit - Say line'), +(@ZEPIK,0,11 ,0,11,0,100,0,0,0,0,0,11,@WOLVARLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Cast Wolvar Location Periodic'), +(@ZEPIK,0,12 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@ZEPIK,0,13 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Goregek - OOC - Set Phase 2'), +(@ZEPIK,0,14 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Agro - Set Phase 1'), +(@ZEPIK,0,15 ,0,38,0,100,0,1,2,0,0,1,4,5000,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Data Set - Say'), +(@ZEPIK,0,16 ,0,52,0,100,0,4,@ZEPIK,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Zepik - On Text Over - Say'), +(@ZEPIK,0,17,0,8,2,100,0,@CHICKENLOCATIONPING,0,6000,10000,11,@CHICKENNET,0,0,0,0,0,19,@CHICKENESCAPEE,5,0,0,0,0,0, 'Zepik - On spellhit - Cast Chicken Net'), +(@LAFOO,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spellhit - Say'), +(@LAFOO,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Linked with Previous Event - Run Script'), +(@LAFOO,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Cast Gorloc Location Periodic'), +(@LAFOO,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@LAFOO,0,4 ,0,38, 0,100,0,1,1,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Data Set - Say'), +(@GORLOCTREASURESCRIPT,9,0 ,0,61, 0,100,0,0,0,0,0,69,0,0,0,0,0,0,11,28362,10,0,0,0,0,0, 'Lafoo - Script - Move to Glinting Dirt'), +(@GORLOCTREASURESCRIPT,9,1 ,0,61, 0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,9,@GLINTINGDIRT,0,2,0,0,0,0, 'Lafoo - Script - Set Data'), +(@GORLOCTREASURESCRIPT,9,2 ,0,61, 0,100,0,1500,1500,0,0,11,51405,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Script - Cast Digging for Treasure'), +(@GORLOCTREASURESCRIPT,9,3 ,0,61, 0,100,0,5000,5000,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - Script - Evade'), +(@LAFOO,0,6 ,0,0, 0,100,0,0,5000,10000,12000,11,52931,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Lafoo - IC - Cast Toxic Spit'), +(@LAFOO,0,7 ,0,2,0,100,0,0,50,60000,60000,11,52940,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Friendly Health - Cast Sleepy Time'), +(@LAFOO,0,8 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Spawn - Set React State'), +(@LAFOO,0,9 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Creature Death - Say'), +(@LAFOO,0,10 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - OOC - Say'), +(@LAFOO,0,11,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On spellhit - Say line'), +(@LAFOO,0,12,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On spellhit - Despawn'), +(@LAFOO,0,13,0,19,0,100,0,12572,0,0,0,85,@SEEINVIS,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Lafoo - On Quest Accept - Invoker Cast Rainspeaker Treasures: See Invisibility'), +(@LAFOO,0,14 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - OOC - Set Phase 2'), +(@LAFOO,0,15 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lafoo - On Agro - Set Phase 1'), +(@JALOOT,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spellhit - Say'), +(@JALOOT,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - Linked with Previous Event - Run Script'), +(@JALOOT,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Gorloc Location Periodic'), +(@JALOOT,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@JALOOT,0,4 ,0,38, 0,100,0,1,1,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Data Set - Say'), +(@JALOOT,0,6,0,0,0,100,0,9000,15000,20000,25000,11,52943,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Lightning Whirl'), +(@JALOOT,0,7,0,0,0,100,0,5000,8000,15000,18000,11,52944,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Lightning Strike'), +(@JALOOT,0,8,0,0,0,100,0,7000,15000,20000,25000,11,52964,2,0,0,0,0,5,0,0,0,0,0,0,0, 'Jaloot - IC - Cast Spark Frenzy'), +(@JALOOT,0,9,0,2,0,100,0,0,30,30000,45000,11,52969,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Less than 30% HP - Cast Energy Siphon'), +(@JALOOT,0,10 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Set React State'), +(@JALOOT,0,11 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Creature Death - Say'), +(@JALOOT,0,12 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - OOC - Say'), +(@JALOOT,0,13,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Say line'), +(@JALOOT,0,14,0,11,0,100,0,0,0,0,0,11,@JALOOTSINTENSITY,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Spawn - Cast Jaloot''s Intensity'), +(@JALOOT,0,15,0,8,0,100,0,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Despawn'), +(@JALOOT,0,16,0,8,2,100,0,@SPEARBORNAURA,0,40000,70000,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On spellhit - Say line'), +(@JALOOT,0,17 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - OOC - Set Phase 2'), +(@JALOOT,0,18 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Jaloot - On Agro - Set Phase 1'), +(@MOODLE,0,0 ,1,8, 2,100,1,@TREASUREPING,0,60000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spellhit - Say'), +(@MOODLE,0,1 ,0,61, 0,100,0,0,0,0,0,80,@GORLOCTREASURESCRIPT,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - Linked with Previous Event - Run Script'), +(@MOODLE,0,2 ,0,11,0,100,0,0,0,0,0,11,@GORLOCLOCATIONPERIODIC,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Cast Gorloc Location Periodic'), +(@MOODLE,0,3 ,0,11,0,100,0,0,0,0,0,11,@SHOLAZARGUARDIANHEARTBEAT,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Cast Sholazar Guardian Heartbeat'), +(@MOODLE,0,4 ,0,0, 0,100,0,0,5000,20000,30000,11,52974,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - IC - Cast Vicious Roar'), +(@MOODLE,0,5 ,0,20, 0,100,0,12580,0,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Quest Complete - Say'), +(@MOODLE,0,6 ,0,0, 0,100,0,0,5000,20000,24000,11,52973,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Moodle - IC - Cast Frost Breath'), +(@MOODLE,0,7,0,0,0,100,0,9000,15000,20000,25000,11,52979,0,0,0,0,0,5,0,0,0,0,0,0,0, 'Moodle - IC - Cast Whirlwind'), +(@MOODLE,0,8,0,0,0,100,0,2000,10000,40000,50000,11,52972,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - IC - Cast Dispersal'), +(@MOODLE,0,9 ,0,2,0,100,0,0,50,60000,60000,11,52979,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On less than 50% HP - Cast Frigid Absorbtion'), +(@MOODLE,0,10 ,0,11,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Spawn - Set React State'), +(@MOODLE,0,11 ,0,5,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Creature Death - Say'), +(@MOODLE,0,12 ,0,1,0,100,0,10000,40000,45000,90000,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - OOC - Say'), +(@MOODLE,0,13,0,8,0,100,0,@RAINSPEAKERAURA,0,45000,70000,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Say line'), +(@MOODLE,0,14,0,8,0,100,1,@DESSAWNRETAINER,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Despawn'), +(@MOODLE,0,15,0,8,2,100,0,@MOSSWALKERAURA,0,40000,70000,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On spellhit - Say line'), +(@MOODLE,0,16 ,0,61, 0,100,0,0,0,0,0,8,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - Linked with Previous Event - Run Passive'), +(@MOODLE,0,17 ,0,19, 0,100,0,12581,0,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Quest Accept - Say'), +(@MOODLE,0,18 ,0,1,0,100,0,10000,10000,10000,10000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - OOC - Set Phase 2'), +(@MOODLE,0,19 ,0,4,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Moodle - On Agro - Set Phase 1'), +(@RAINSPEAKERBUNNY,0,0,0,10,0,100,0,1,150,10000,10000,11,@RAINSPEAKERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Rainspeaker Canopy Bunny - On update OOC - Spellcast Rainspeaker Canopy Aura'), +(@FRENZYBUNNY,0,0,0,10,0,100,0,1,150,10000,10000,11,@FRENZYAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Frenzyheart Hill Bunny - On update OOC - Spellcast Frenzyheart Hill Aura'), +(@MOSSWALKERBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@MOSSWALKERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Mosswalker Village Bunny - On update OOC - Spellcast Mosswalker Village Aura'), +(@MOSSWALKERBUNNY,0,1,0,10,0,100,0,1,200,1000,1000,85,@ANGRYGORLOCCREDIT,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Mosswalker Village Bunny - On update OOC - Cast quest credit'), +(@MISTWHISPERBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@MISTWHISPERAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Mistwhisper Refuge Bunny - On update OOC - Spellcast Mistwhisper Refuge Aura'), +(@SPEARBORNBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SPEARBORNAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Spearborn Encampment Bunny - On update OOC - Spellcast Spearborn Encampment Aura'), +(@KARTAKHOLDBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@KARTAKHOLDAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Kartak Hold Bunny - On update OOC - Spellcast Kartak Hold Aura'), +(@SPARKTOUCHEDBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SPARKTOUCHEDAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sparktouched Haven Bunny - On update OOC - Spellcast Sparktouched Haven Aura'), +(@SAPPHIREHIVEBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SAPPHIREHIVEAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sapphire Hive Bunny - On update OOC - Spellcast Sapphire Hive Aura'), +(@SKYREACHPILLARBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@SKYREACHPILLARAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Skyreach Pillar Bunny - On update OOC - Spellcast Skyreach Pillar Aura'), +(@LIFEBLOODPILLARBUNNY,0,0,0,10,0,100,0,1,200,10000,10000,11,@LIFEBLOODPILLARAURA,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Lifeblood Pillar Bunny - On update OOC - Spellcast Lifeblood Pillar Aura'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@SPARKLINGHARE; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@SPARKLINGHARE; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@SPARKLINGHARE,0,0 ,0,6, 0,100,0,0,0,0,0,11,@BLESSINGOFTHESPARKINGHARE,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Sparking Hare - On Death - Cast Blessing of the Sparkling Hare'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@GLINTINGBUG; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@GLINTINGBUG; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@GLINTINGBUG,0,0 ,0,11, 0,100,0,0,0,0,0,89,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Glinting Bug - On Spawn - Set Random Movement'); + +DELETE FROM `creature_text` WHERE `entry` IN(@LAFOO,@JALOOT,@MOODLE,@GOREGEK,@DAJIK,@ZEPIK); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@LAFOO, 0, 0, 'Ooh! Shinies!', 12, 0, 18, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 1, 'Maybe more shiny bugs! We like bugs!', 12, 0, 17, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 2, 'Treasure for Lafoo! Treasure for shrine!', 12, 0, 17, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 3, 'Dig, dig, dig...', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 4, 'Crunchy bugs so delicious. Want?', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 0, 5, 'That weird. Someone took our bugs. You have maybe?', 12, 0, 16, 0, 0, 0, 'Lafoo'), +(@LAFOO, 1, 0, 'No come back this time!', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 0, 'One day maybe you can be Soo-dryskin. You like?', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 1, 'You have pie? Someone gave us pie year ago. Really yummy.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 2, 'Big comfy tree. Good Home.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 3, 'Never meet Great Ones. Nope, just met their shrines.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 2, 4, 'You got funny looking eyeballs.', 12, 0, 20, 0, 0, 0, 'Lafoo'), +(@LAFOO, 3, 0, 'Home good, but not stay long! More adventures!.', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@LAFOO, 4, 0, 'Hiss... hiss... dead. All dead', 12, 0, 100, 0, 0, 0, 'Lafoo'), +(@JALOOT, 0, 0, 'Shiny things! Shiny things! Not as shiny as my crystal, but still shiny!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 1, 'More treasures! Treasures of all kinds! Yay treasures!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 2, 'Can never have too many shiny crystals! Nope!', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 0, 3, 'We are fast digger! Really fast! See... all done! That was fast, huh?', 12, 0, 25, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 0, 'You like that? Bet not! Bet not cause you dead! Hahah!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 1, 'Vic...tor...ious! Dun nun nun dun da da!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 1, 2, 'Killing Spree!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 0, 'Mistcaller really good at controlling weather with shrine. They know just which crystals to use! Really good!', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 1, 'Ever trip over own feet? We have. Kind of hurt. No do it, not fun. Nope.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 2, 'Want us to help with something? What we help with? We good at helping.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 3, 'Hello! You''re pretty strong and nice and stuff. I like you. Lets stay friends, okay?', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 4, 'Misty. Very misty. Seem sort of misty to you? Maybe not so much.', 12, 0, 16, 0, 0, 0, 'Jaloot'), +(@JALOOT, 2, 5, 'Lets go jump off tree! Fun fun!', 12, 0, 15, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 0, 'Chase the hatchlings! Chase the hatchlings! So fast!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 1, 'Great Ones keep home safe because they like Oracles I think! They know we good and nice.', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 3, 2, 'Home home home... place of the shinies!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 0, 'We know you have dragon thing! We not scared! We going to get you and dragon thing!', 12, 0, 34, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 1, 'Teach you to steal our treasures! Our treasures are... ours, okay?', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 4, 2, 'Time to hide puppy-men! We are coming for you!', 12, 0, 33, 0, 0, 0, 'Jaloot'), +(@JALOOT, 5, 0, 'Tartek no match for you! You got the skills. Yeah!', 12, 0, 100, 0, 0, 0, 'Jaloot'), +(@MOODLE, 0, 0, 'What the heck are shiny rabbits doing here anyway?', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 1, 'Here I am, digging up some useless bauble on the will of someone I just met...does that seem right to you?', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 2, 'Hey, maybe we''ll find some more useless bugs!', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 0, 3, 'Yay... more dirt.', 12, 0, 25, 0, 0, 0, 'Moodle'), +(@MOODLE, 1, 0, 'I can''t believe ... they''re all ... dead', 12, 0, 50, 0, 0, 0, 'Moodle'), +(@MOODLE, 1, 1, 'Another one falls to our Onslaught, As it should be.', 12, 0, 50, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 0, 'There some reason why we''re still here? I''d love to hear it', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 1, 'Yeah, let''s go now', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 2, 2, 'I''m done here', 12, 0, 34, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 0, 'Going to go take a nap? I apologize in advance for accidentally stepping on your face while you sleep.', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 1, 'Planning to sit on your butt some more, or are we going to go do something that''s actually useful?', 12, 0, 34, 0, 0, 0, 'Moodle'), +(@MOODLE, 3, 2, 'Here I am, brain the size of a planet, and they ask me to take you to the other village. Call that job satisfaction? ''Cause I don''t.', 12, 0, 33, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 0, 'The Mosswalkers were good people... they did not deserve this.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 1, 'I know I talk down to them, but I never want to see any of my people die.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 2, 'It''s good to see some of the mosswalker were more resilient than I thought.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 3, 'It''s hard to believe any of them survived this.', 12, 0, 17, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 4, 'There are more that might still be alive! We need to keep moving.', 12, 0, 16, 0, 0, 0, 'Moodle'), +(@MOODLE, 4, 5, 'Where are they dragging those bodies? What are they doing to them?', 12, 0, 16, 0, 0, 0, 'Moodle'), +(@MOODLE, 5, 0, 'This fight''s all yours', 12, 0, 10, 0, 0, 0, 'Moodle'), +(@MOODLE, 6, 0, 'It''s a small comfort to see that they haven''t brought any back in undeath.', 12, 0, 100, 0, 0, 0, 'Moodle'), +(@GOREGEK,0,0,'Home! You better have brought back meat for Goregek, slave.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,1,'Goregek get some sleep. Go bring foodstuffs back, slave thing.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,2,'Goregek go get drink. You sit in corner til Goregek ready.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,3,'Goregek hungry. Go get on fire spit, slave thing. Tell Goregek when you well roasted.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,4,'Gorgek gonna catch chicken good!',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,5,'You wait until Goregek ready.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,0,6,'You wait, slave thing. Goregek eating.',12,0,20,0,0,0,'Goregek'), +(@GOREGEK,1,0,'Goregek best hunter... ever.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,1,'Hah! Goregek''s kill!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,2,'Next time, maybe Goregek let you try.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,3,'I stabbed it in the face! Goregek so good.',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,4,'Squeal! Squeal! So good!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,5,'Frenzyheart the strongest!',12,0,15,0,0,0,'Goregek'), +(@GOREGEK,1,6,'That how it done, slave thing. Maybe you figure out how someday.',12,0,10,0,0,0,'Goregek'), +(@GOREGEK,2,0,'Why Goregek even bring you. You useless.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,1,'Elder maybe says other stuff, but you always be slave thing to Goregek.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,2,'Pitch was weakling anyway... why else you think Goregek not bother with him?',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,2,3,'You just get yourself beat up! Hah! You so dumb, slave thing.',12,0,25,0,0,0,'Goregek'), +(@GOREGEK,3,0,'Careful slave thing, the big bad softnuckles might eat you! Hah!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,1,'Hardknuckles still walk on hands... seem kind of dumb to Goregek.',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,2,'Run away dumb softknuckle! We gonna poke you more!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,3,'Run away softknuckle! Goregek gonna get you!',12,0,13,0,0,0,'Goregek'), +(@GOREGEK,3,4,'You just watch slave thing, Goregek take care of these hardknuckles!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,5,'Better not get in Goregek''s way!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,6,'Get out of way silly slave thing! Goregek''s kill!',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,3,7,'There were hundreds of times these hardknuckles before Goregek.',12,0,12,0,0,0,'Goregek'), +(@GOREGEK,4,0,'Hah! Goregek the greatest hunter ever! Goregek get biggest hardknuckle!',12,0,100,0,0,0,'Goregek'), +(@GOREGEK,5,0,'Frenzyheart feed Kartak big-tongue so Kartak not eat us. That why we smarter than you, slave thing.',12,0,100,0,0,0,'Goregek'), +(@DAJIK,0,0,'Frenzyheart came here not long ago for new home... big-tongue homes pretty nice, so we maybe take those too. They ugly anyway.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,1,'Lot of strong Frenzyheart here. Dajik taught most of them. First time I teach something like you though. You not a Frenzyheart, you know.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,2,'Let''s just eat bristlepine instead, okay? All done with chasing.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,3,'There reason Frenzyheart not chase back chickens. Look kind of dumb to lose to chicken.',12,0,12,0,0,0,'Dajik'), +(@DAJIK,0,4,'Maybe you not notice, chicken move kind of fast.',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,5,'Time for more smart Dajik tip! If Goregek let chickens out again, make Goregek get chickens back again.',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,6,'I placed most of the spikes. Good amount of pointiness I think. You like?',12,0,13,0,0,0,'Dajik'), +(@DAJIK,0,7,'Oh! Dajik has idea! Make chicken sounds and maybe they come to you!',12,0,13,0,0,0,'Dajik'), +(@DAJIK,1,0,'Get the stuff off of body! Dajik hate it when he go skin something and there stuff in the way. So annoying.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,1,'Did you see face? Looked so scared, "Ah, big thing going to smash me!" Hah.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,2,'Hah! Maybe you learn a little after all!',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,3,'Yes! Stab few more time just in case! Stab good!',12,0,20,0,0,0,'Dajik'), +(@DAJIK,1,4,'Not sure how thing got here. Not matter if dead though',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,0,'We came for something, yes? Can''t remember.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,1,'Make sure you not forget anything! I forgot stuff once.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,2,'Dajik not think he seen you eat anything. You eat sometimes, yeah?',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,3,'I was going to draw picture of best attack plan... but you have my chalk.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,2,4,'Time for more smart Dajik tip! Make sure thing dead before reach in mouth for loots.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,0,'Seem like there more wasps every time Dajik come back. Why they not run out?',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,1,'Time for more smart Dajik tip! Try not to catch stinger with face. Not work so much.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,2,'In case you wonder, wasp sting not feel so good. No need to try.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,3,'Drone things not as tough as they look. Wasp things a bit nastier.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,3,4,'Try not to catch stinger with face. Not work so much.',12,0,20,0,0,0,'Dajik'), +(@DAJIK,4,0,'No! You killed the queen thing! What have you... wait, nevermind. Sorry, that okay.',12,0,100,0,7000,0,'Dajik'), +(@DAJIK,5,0,'Dajik''s last learner eaten by sand-thing. We do better this time though!',12,0,100,0,0,0,'Dajik'), +(@DAJIK,6,0,'This not first queen slain by Frenzyheart. Seem like there always more.',12,0,100,0,0,0,'Dajik'), +(@DAJIK,7,0,'Sometimes big-tongues try to come get crystals. Not now because they not like it when we kill them.',12,0,34,0,0,0,'Dajik'), +(@DAJIK,7,1,'Time for more smart Dajik tip! Crystals work little too good for back scratch. No try.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,7,2,'Something big make pillars and crystals and everything. Frenzyheart not care much cause it not here anymore.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,8,0,'If you here to poke more softnuckles, Dajik going to poke you too.That a bad Goregek habit.',12,0,50,0,0,0,'Dajik'), +(@DAJIK,8,1,'Huh... where are we? This not right. I not tell you find hardknuckles, did I?',12,0,50,0,0,0,'Dajik'), +(@DAJIK,9,0,'Time for more smart Dajik tip! Lot of dead things mean lot of chance of being dead thing. Dajik leaving now.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,9,1,'Dead thing there already learn lesson of broken pillar. Leave this lesson for dumb, dead things. Going home now.',12,0,33,0,0,0,'Dajik'), +(@DAJIK,9,2,'You all done with learning! Yup! All done! Dajik leave you and evil red pillar thing now.',12,0,34,0,0,0,'Dajik'), +(@ZEPIK,0,0,'Bring back good meat and the camp treat you like high-shaman for a day. Good deal.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,1,'Elder Harkek pretty good Frenzyheart. He help me a lot when I was littler and not liking Dajik.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,2,'I not in a big hurry. We can rest here a while if want.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,3,'I not live here always... I traveled lot of world on my own not long ago. I like all the stories of beasts and dragons and gods and stuff.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,0,4,'You should go let chickens out again and say Goregek did it. Never get old.',12,0,20,0,0,0,'Zepik'), +(@ZEPIK,1,0,'Hahah! You see that? Lightning bolt hit him right in the head!',12,0,33,0,0,0,'Zepik'), +(@ZEPIK,1,1,'Good one! It not even see it coming.',12,0,33,0,0,0,'Zepik'), +(@ZEPIK,1,2,'No more play?',12,0,34,0,0,0,'Zepik'), +(@ZEPIK,2,0,'You ever fought big dragon or god or anything? Zepik like hearing stories.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,1,'You pretty good! Natural at hunt, like me.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,2,'Goregek think he the boss of everyone, but he eat too much and hunt too little.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,3,'Bring back good meat and the camp treat you like high-shaman for a day. Good deal.',12,0,12,0,0,0,'Zepik'), +(@ZEPIK,2,4,'Dajik forget what he doing, where he at... sometime even forget his own name. Make him not so good teacher sometimes.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,5,'Elder Harkek pretty good Frenzyheart. He help me a lot when I was littler and not liking Dajik.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,6,'Goregek never ''stumble'' into chicken hut... Goregek always have to feed his dumb belly. Always one chicken missing when we catch them all.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,2,7,'Dajik tried to show me ways of hunt, but I do better when I do things my way.',12,0,13,0,0,0,'Zepik'), +(@ZEPIK,3,0,'Eat it big-tongues!',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,1,'Hah! Leave some for Zepik too.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,2,'That lake near here actually full of sea things. Not sure how it all get here... maybe in floods?',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,3,'I think one reason I like hunting big-tongues so much... they not as dumb as the other hunts. They give a real fight.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,4,'Mist big-tongues are smart with their shrine thing sometimes... cover whole area with mist and it get hard to find any.',12,0,14,0,0,0,'Zepik'), +(@ZEPIK,3,5,'Hah! This the fun part!',12,0,15,0,0,0,'Zepik'), +(@ZEPIK,3,6,'Flame! Death! Destruction! The black fire rages within my heart! I must... release it! Hahah!',12,0,15,0,0,0,'Zepik'), +(@ZEPIK,4,0,'Trust me - you going love this!',12,0,100,0,0,0,'Zepik'), +(@ZEPIK,5,0,'BOOM! That so good! More! More!',12,0,100,0,0,0,'Zepik'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9678 AND `SourceEntry`=13137; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (@FRENZYAURA,@RAINSPEAKERAURA,@WOLVARPING,@GORLOCPING,@DESSAWNRETAINER,@TREASUREPING,@DIGGINGFORTEASURE,@MOSSWALKERAURA,@SPEARBORNAURA,@MISTWHISPERAURA,@SAPPHIREHIVEAURA,@SKYREACHPILLARAURA,@CHICKENLOCATIONPING,51846); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,7,@FRENZYAURA,0,31,@GOREGEK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Goregek the Bristlepine Hunter'), +(13,7,@FRENZYAURA,1,31,@DAJIK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Dajik the Wasp Hunter'), +(13,7,@FRENZYAURA,2,31,@ZEPIK,0,0,0,0,'','Spell Frenzyheart Hill Aura targets Zepik the Gorloc Hunter'), +(13,7,@RAINSPEAKERAURA,0,31,@LAFOO,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Lafoo'), +(13,7,@RAINSPEAKERAURA,1,31,@MOODLE,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Jaloot'), +(13,7,@RAINSPEAKERAURA,2,31,@JALOOT,0,0,0,0,'','Spell Rainspeaker Canopy Aura targets Moodle'), +(13,7,@WOLVARPING,0,31,@GOREGEK,0,0,0,0,'','Spell Wolvar Location Ping targets Goregek the Bristlepine Hunter'), +(13,7,@WOLVARPING,1,31,@DAJIK,0,0,0,0,'','Spell Wolvar Location Ping targets Dajik the Wasp Hunter'), +(13,7,@WOLVARPING,2,31,@ZEPIK,0,0,0,0,'','Spell Wolvar Location Ping targets Zepik the Gorloc Hunter'), +(13,7,@GORLOCPING,0,31,@LAFOO,0,0,0,0,'','Spell Gorloc Location Ping targets Lafoo'), +(13,7,@GORLOCPING,1,31,@JALOOT,0,0,0,0,'','Spell Gorloc Location Ping targets Jaloot'), +(13,7,@GORLOCPING,2,31,@MOODLE,0,0,0,0,'','Spell Gorloc Location Ping targets Moodle'), +(13,7,@DESSAWNRETAINER,0,31,@LAFOO,0,0,0,0,'','Spell Dessawn Retainer targets Lafoo'), +(13,7,@DESSAWNRETAINER,1,31,@DAJIK,0,0,0,0,'','Spell Dessawn Retainer targets Dajik the Wasp Hunter'), +(13,7,@DESSAWNRETAINER,2,31,@ZEPIK,0,0,0,0,'','Spell Dessawn Retainer targets Zepik the Gorloc Hunter'), +(13,7,@DESSAWNRETAINER,3,31,@JALOOT,0,0,0,0,'','Spell Dessawn Retainer targets Jaloot '), +(13,7,@DESSAWNRETAINER,4,31,@MOODLE,0,0,0,0,'','Spell Dessawn Retainer targets Moodle'), +(13,7,@DESSAWNRETAINER,5,31,@GOREGEK,0,0,0,0,'','Spell Dessawn Retainer targets Goregek'), +(13,7,@TREASUREPING,0,31,@LAFOO,0,0,0,0,'','Spell looking for treasure ping targets Lafoo'), +(13,7,@TREASUREPING,1,31,@JALOOT,0,0,0,0,'','Spell looking for treasure ping targets Jaloot '), +(13,7,@TREASUREPING,2,31,@MOODLE,0,0,0,0,'','Spell looking for treasure ping targets Moodle'), +(13,7,@CHICKENLOCATIONPING,0,31,@GOREGEK,0,0,0,0,'','Spell chicken ping targets Goregek'), +(13,7,@CHICKENLOCATIONPING,1,31,@DAJIK,0,0,0,0,'','Spell chicken ping targets Dajik '), +(13,7,@CHICKENLOCATIONPING,2,31,@ZEPIK,0,0,0,0,'','Spell chicken ping targets Zepik'), +(13,7,@DIGGINGFORTEASURE,0,31,@GLINTINGDIRT,0,0,0,0,'','digging for treasure targets glinting dirt'), +(13,7,@MOSSWALKERAURA,0,31,@MOODLE,0,0,0,0,'','Mosswalker village aura targets moodle'), +(13,7,@SPEARBORNAURA,0,31,@JALOOT,0,0,0,0,'','spearborn encampment aura targets moodle'), +(13,7,@MISTWHISPERAURA,0,31,@ZEPIK,0,0,0,0,'','mistwhisper refuge aura targets zepik'), +(13,7,@SAPPHIREHIVEAURA,0,31,@DAJIK,0,0,0,0,'','sapphire hive aura targets dajik'), +(13,7,@SKYREACHPILLARAURA,0,31,@DAJIK,0,0,0,0,'','skyreach pillar aura targets dajik'), +(13,7,51846,0,31,@CHICKENESCAPEE,0,0,0,0,'','Scared Chicken targets only chicken escapee'), +(14,9678,13137,0,5,1104,7,0,0,0,'','Shaman Vekjik - Show different gossip if player is hated, hostile or unfriendly with Frenzyheart Tribe'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN(@GLINTINGDIRT,@LAFOO,@JALOOT,@MOODLE,@GOREGEK,@DAJIK,@ZEPIK,@MOSSWALKERBUNNY) AND `SourceId`=0; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(22,17,@GOREGEK,0,0,9,0,12702,0,0,0,0, '', 'Goregek SAI only activates if player is on and has not completed the Chicken Party!'), +(22,17,@GOREGEK,0,0,29,0,@CHICKENESCAPEE,5,0,0,0, '', 'Execute SAI only if there is chicken escapee within 5 yards'), +(22,21,@DAJIK,0,1,9,0,12532,0,0,0,0, '', 'Dajik SAI only activates if player is on and has not completed Flown the Coop!'), +(22,21,@DAJIK,0,1,29,0,@CHICKENESCAPEE,5,0,0,0, '', 'Execute SAI only if there is chicken escapee within 5 yards'), +(22,21,@DAJIK,0,0,9,0,12702,0,0,0,0, '', 'Dajik SAI only activates if player is on and has not completed the Chicken Party!'), +(22,21,@DAJIK,0,0,29,0,@CHICKENESCAPEE,5,0,0,0, '', 'Execute SAI only if there is chicken escapee within 5 yards'), +(22,18,@ZEPIK,0,0,9,0,12702,0,0,0,0, '', 'Dajik SAI only activates if player is on and has not completed the Chicken Party!'), +(22,18,@ZEPIK,0,0,29,0,@CHICKENESCAPEE,5,0,0,0, '', 'Execute SAI only if there is chicken escapee within 5 yards'), +(22,1,@LAFOO,0,0,9,0,12704,0,0,0,0, '', 'Lafoo SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@LAFOO,0,0,29,0,@GLINTINGDIRT,10,0,0,0, '', 'Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@LAFOO,0,1,9,0,12572,0,0,0,0, '', 'Lafoo SAI only activates if player is on and has not completed the Gods like shiny things'), +(22,1,@LAFOO,0,1,29,0,@GLINTINGDIRT,10,0,0,0, '', 'Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@JALOOT,0,0,9,0,12704,0,0,0,0, '', 'Jaloot SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@JALOOT,0,0,29,0,@GLINTINGDIRT,10,0,0,0, '', 'Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@MOODLE,0,0,9,0,12704,0,0,0,0, '', 'Moodle SAI only activates if player is on and has not completed the Appeasing the Great rainstone'), +(22,1,@MOODLE,0,0,29,0,@GLINTINGDIRT,10,0,0,0, '', 'Execute SAI only if there is glinting dirt within 5 yards'), +(22,1,@GLINTINGDIRT,0,0,29,1,@LAFOO,5,0,0,0, '', 'Execute SAI only if Lafoo within 2 yards'), +(22,1,@GLINTINGDIRT,0,1,29,1,@JALOOT,5,0,0,0, '', 'Execute SAI only if Jaloot within 2 yards'), +(22,1,@GLINTINGDIRT,0,2,29,1,@MOODLE,5,0,0,0, '', 'Execute SAI only if Moodle within 2 yards'), +(22,13,@MOODLE,0,0,23,1,4297,0,0,1,0, '', 'Moodle dont execute SAI in Mosswalker Village'), +(22,9,@GOREGEK,0,0,23,1,4303,0,0,1,0, '', 'Goregek dont execute SAI in Hardknuckle Clearing'), +(22,10,@ZEPIK,0,0,23,1,4306,0,0,1,0, '', 'Zepik dont execute SAI in Mistwhisper Refuge'), +(22,12,@GOREGEK,0,0,23,1,4303,0,0,0,0, '', 'Goregek execute SAI in only in Hardknuckle Clearing'), +(22,9,@DAJIK,0,0,23,1,4304,0,0,1,0, '', 'Dajik Dont execute SAI in Sapphire Hive'), +(22,9,@DAJIK,0,0,23,1,4303,0,0,1,0, '', 'Dajik execute SAI in Hardknuckle Clearing'), +(22,9,@DAJIK,0,0,23,1,4388,0,0,1,0, '', 'Dajik execute SAI in Wintergrasp River'), +(22,9,@DAJIK,0,0,23,1,4295,0,0,1,0, '', 'Dajik execute SAI in The Sundered Shard'), +(22,19,@DAJIK,0,0,23,1,4303,0,0,0,0, '', 'Dajik execute SAI only in Hardknuckle Clearing'), +(22,11,@LAFOO,0,0,23,1,4291,0,0,1,0, '', 'Lafoo dont execute sai in rainspeaker canopy'), +(22,13,@JALOOT,0,0,23,1,4291,0,0,1,0, '', 'Jaloot dont execute sai in rainspeaker canopy'), +(22,13,@JALOOT,0,1,23,1,4308,0,0,1,0, '', 'Jaloot dont execute sai in spearborn encampment'), +(22,13,@MOODLE,0,0,23,1,4291,0,0,1,0, '', 'Moodle dont execute sai in rainspeaker canopy'), +(22,9,@GOREGEK,0,0,23,1,4292,0,0,1,0, '', 'Goregek dont execute sai in frenzyheart hill'), +(22,9,@DAJIK,0,0,23,1,4292,0,0,1,0, '', 'Dajik dont execute sai in frenzyheart hill'), +(22,10,@ZEPIK,0,0,23,1,4292,0,0,1,0, '', 'Zepik dont execute sai in frenzyheart hill'), +(22,2,@MOSSWALKERBUNNY,0,0,1,0,@SHOLAZARGUARDIANHEARTBEAT,0,0,0,0, '', 'Mosswalker Bunny execute SAI only if player has sholazar guardian heartbeat aura'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @SOFTKNUCKLE; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@SOFTKNUCKLE; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@SOFTKNUCKLE,0,0,0,8,0,20 ,0,@SCAREDSOFTKNUCKLE,0,10000,10000,45,1,1,0,0,0,0,10,100797,@HARDKNUCKLEMATRIARCH,0,0,0,0,0, 'Softknuckle - On Spellhit - Set Data on Hardknuckle Matriach'); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @HARDKNUCKLE; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@HARDKNUCKLE; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@HARDKNUCKLE; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@HARDKNUCKLE,0,0,0,9,0,100,0,10,30,15000,21000,11,49758,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Hardknuckle Charger - On Range - Cast Charge'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @HARDKNUCKLEMATRIARCH; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@HARDKNUCKLEMATRIARCH; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@HARDKNUCKLEMATRIARCH; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@HARDKNUCKLEMATRIARCH,0,0,1,4,0,100,0,0,0,0,0,11,54287,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - On Agro - Cast Enrage'), +(@HARDKNUCKLEMATRIARCH,0,1,0,61,0,100,0,0,0,0,0,1 ,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Say'), +(@HARDKNUCKLEMATRIARCH,0,2,0,0,0,100,0,6000,10000,12000,15000,11 ,61580,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - In Combat - Cast Cast Thunderstomp'), +(@HARDKNUCKLEMATRIARCH,0,3,4,38,0,100,0,1,1,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - On Data Set 1 1 - Set Data 10'), +(@HARDKNUCKLEMATRIARCH,0,4,5,61,0,100,0,0,0,0,0,19,756,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Remove unit flags'), +(@HARDKNUCKLEMATRIARCH,0,5,6,61,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Set Visible'), +(@HARDKNUCKLEMATRIARCH,0,6,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,21,500,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Attack closest player'), +(@HARDKNUCKLEMATRIARCH,0,7,8,11,0,100,0,0,0,0,0,18,756,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - On spawn - Add unit flags'), +(@HARDKNUCKLEMATRIARCH,0,8,0,61,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Set Invisible'), +(@HARDKNUCKLEMATRIARCH,0,9,10,21,0,100,0,0,0,0,0,18,756,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - On Creature reached home - Add unit flags'), +(@HARDKNUCKLEMATRIARCH,0,10,0,61,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Set Invisible'), +(@HARDKNUCKLEMATRIARCH,0,11,12,6,0,100,0,0,0,0,0,45,1,1,0,0,0,0,9,@GOREGEK,0,50,0,0,0,0, 'Hardknuckle Matriarch - On Death Send Data to Goregek'), +(@HARDKNUCKLEMATRIARCH,0,12,0,61,0,100,0,0,0,0,0,41,60000,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hardknuckle Matriarch - Linked with Previous Event - Despawn after 1m'); + +DELETE FROM `creature_ai_texts` WHERE `entry`=-738; +DELETE FROM `creature_text` WHERE `entry` =@HARDKNUCKLEMATRIARCH; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@HARDKNUCKLEMATRIARCH, 0, 0, 'We are Not Amused', 12, 0, 100, 0, 0, 0, 'Hardknuckle Matriarch'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` =@SOFTKNUCKLE; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(22,2,@SOFTKNUCKLE,0,0,23,0,4303,0,0,0,0, '', 'Softknuckle - Only execute SAI in hardknuckle clearing'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`IN(13,17) AND `SourceEntry`=@SCAREDSOFTKNUCKLE; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(17,0,@SCAREDSOFTKNUCKLE,0,0,31,1,3,@SOFTKNUCKLE,0,0,0, '', 'Scared Softknuckle only hits Softknuckle'), +(13,0,@SCAREDSOFTKNUCKLE,0,0,31,1,3,@SOFTKNUCKLE,0,0,0, '', 'Scared Softknuckle only hits Softknuckle'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @SAPPHIREQUEEN; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@SAPPHIREQUEEN; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@SAPPHIREQUEEN; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@SAPPHIREQUEEN,0,0,0,0,0,100,0,6000,9000,9000,14000,11,48193,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Sapphire Hive Queen - IC - Cast Poison Stinger'), +(@SAPPHIREQUEEN,0,1,0,2,0,100,0,0,30,12000,15000,11,54761,1,0,0,0,0,1,0,0,0,0,0,0,0, 'Sapphire Hive Queen - On 30% Hp - Cast Enrage'), +(@SAPPHIREQUEEN,0,2,0,6,0,100,0,0,0,0,0,45,1,1,0,0,0,0,9,@DAJIK,0,50,0,0,0,0, 'Sapphire Hive Queen - On Death - Set Data Dajik'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @VENOMTIP; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@VENOMTIP; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@VENOMTIP; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@VENOMTIP,0,0,0,0,0,100,0,7000,9000,17000,20000,11,61550,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Venomtip - IC - Cast Cobra Strike'), +(@VENOMTIP,0,1,0,9,0,100,0,0,30,7000,12000,11,32330,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Venomtip - On Range - Cast Poison Spit'), +(@VENOMTIP,0,2,0,6,0,100,0,0,0,0,0,45,1,1,0,0,0,0,9,@LAFOO,0,50,0,0,0,0, 'Venomtip - On Death - Set Data Lafoo'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @SERFEXTHEREAVER; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@SERFEXTHEREAVER; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@SERFEXTHEREAVER; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@SERFEXTHEREAVER,0,0,1,1,0,100,0,0,0,60000,90000,11,20567,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - OOC - Cast Submerge Visual'), +(@SERFEXTHEREAVER,0,1,0,61,0,100,0,0,0,0,0,18,33554434,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Set Unselectable and Unattackable Flags'), +(@SERFEXTHEREAVER,0,2,3,4,0,100,0,0,0,0,0,28,20567,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - On Agro - Remove Submerge Visual'), +(@SERFEXTHEREAVER,0,3,4,61,0,100,0,0,0,0,0,28,29147,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Remove Submerge Visual'), +(@SERFEXTHEREAVER,0,4,5,61,0,100,0,0,0,0,0,11,37752,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Cast Stand'), +(@SERFEXTHEREAVER,0,5,6,61,0,100,0,0,0,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Stop Combat Movement'), +(@SERFEXTHEREAVER,0,6,7,61,0,100,0,0,0,0,0,19,33554434,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Remove Unselectable and Unattackable Flags'), +(@SERFEXTHEREAVER,0,7,0,61,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Set Phase 1'), +(@SERFEXTHEREAVER,0,8,0,0,1,100,0,1000,1000,2100,4500,11,20567,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Serfex the Reaver - IC - Cast Poison'), +(@SERFEXTHEREAVER,0,9,10,9,0,100,0,40,60,0,0,11,68909,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - On Range - Cast Submerge Visual'), +(@SERFEXTHEREAVER,0,10,11,61,0,100,0,0,0,0,0,11,29147,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Cast Stand'), +(@SERFEXTHEREAVER,0,11,0,61,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Set Phase 2'), +(@SERFEXTHEREAVER,0,12,13,9,1,100,0,0,8,0,0,28,20567,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - On Range - Remove Submerge Visual'), +(@SERFEXTHEREAVER,0,13,14,61,1,100,0,0,0,0,0,11,37752,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Cast Stand'), +(@SERFEXTHEREAVER,0,14,15,61,1,100,0,0,0,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Stop Combat Movement'), +(@SERFEXTHEREAVER,0,15,0 ,61,1,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Set Phase 1'), +(@SERFEXTHEREAVER,0,16,17,7,0,100,0,0,0,0,0,11,20567,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Evade - Cast Submerge Visual'), +(@SERFEXTHEREAVER,0,17,18,61,0,100,0,0,0,0,0,21,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Allow Combat Movement'), +(@SERFEXTHEREAVER,0,18,19,61,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Linked with Previous Event - Set Phase 0'), +(@SERFEXTHEREAVER,0,19,20,61,0,100,0,0,0,0,0,11,29147,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Evade - Cast Submerge Visual'), +(@SERFEXTHEREAVER,0,20,21,61,0,100,0,0,0,0,0,14,100,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Evade - Set Threat'), +(@SERFEXTHEREAVER,0,21,0,61,0,100,0,0,0,0,0,18,33554434,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Serfex the Reaver - Evade - Set Untargetable flags'), +(@SERFEXTHEREAVER,0,22,0,6,0,100,0,0,0,0,0,45,1,2,0,0,0,0,9,@DAJIK,0,50,0,0,0,0, 'Serfex the Reaver - On Death - Set Data Dajik'); + +DELETE FROM `gameobject` WHERE `guid` IN (@GOBJGUID,@GOBJGUID+1); +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@GOBJGUID,300213,571,1,1,6206.71,4951.67,-98.9126,3.84683,0,0,0.938472,-0.345355,300,0,1), +(@GOBJGUID+1,190502,571,1,1,6206.71,4951.67,-98.9126,3.84683,0,0,0.938472,-0.345355,-5000,0,1); + +DELETE FROM `event_scripts` WHERE `id`IN(18475,18474); +INSERT INTO `event_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`) VALUES +(18475,2,9,@GOBJGUID+1,60,0,0,0,0,0), +(18474,1,10,@MISTWHISPERLIGHTNINGCLOUD,60000,0,6202.683105,4948.736328,-86,0); + +UPDATE `creature_template` SET `AIName`= 'SmartAI',`InhabitType`=4 WHERE `entry`=@MISTWHISPERLIGHTNINGCLOUD; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@MISTWHISPERLIGHTNINGCLOUD; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@MISTWHISPERLIGHTNINGCLOUD,0,0,0,1, 0,100,1,10000,10000,0,0,15,12537,0,0,0,0,0,18,40,0,0,0,0,0,0, 'Mistwhisper Lightning Cloud - OOC - Give Quest Credit'), +(@MISTWHISPERLIGHTNINGCLOUD,0,1,0,1, 0,100,0,3000,5000,2000,11000,11,51172,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Mistwhisper Lightning Cloud - OOC - Cloud to Lightning'), +(@MISTWHISPERLIGHTNINGCLOUD,0,2,3,11, 0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,106338,28273,0,0,0,0,0, 'Mistwhisper Lightning Cloud - On Spawn - Send Data to Arranged Crystal Formation Bunny'), +(@MISTWHISPERLIGHTNINGCLOUD,0,3,0,61,0,100,0,0,0,0,0,45,1,2,0,0,0,0,9,@ZEPIK,0,50,0,0,0,0, 'Mistwhisper Lightning Cloud - Linked with Previous Event - Set Data Zepik'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=51172; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,7,51172,0,0,31,0,3,@MISTWHISPERLIGHTNINGTARGET,0,0,0,0, '', 'Cloud to Lightning hits Mistwhisper Lightning Target'), +(13,7,51172,0,1,31,0,3,@MISTWHISPERLIGHTNINGCLOUD,0,0,0,0, '', 'Cloud to Lightning hits Mistwhisper Lightning Cloud'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ARRANGEDCRYSTALFORMATIONBUNNY; +DELETE FROM `smart_scripts` WHERE `entryorguid` =@ARRANGEDCRYSTALFORMATIONBUNNY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ARRANGEDCRYSTALFORMATIONBUNNY,0,0,1,38, 0,100,0,1,1,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Arranged Crystal Formation Bunny - On Receive Data - Reset Data'), +(@ARRANGEDCRYSTALFORMATIONBUNNY,0,1,2,61, 0,100,0,0,0,0,0,11,51150,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Arranged Crystal Formation Bunny - Linked with Previous Event - Cast Crystal Shatter Visual'), +(@ARRANGEDCRYSTALFORMATIONBUNNY,0,2,3,61, 0,100,0,0,0,0,0,11,51172,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Arranged Crystal Formation Bunny - Linked with Previous Event - Cast Lightning to Cloud'), +(@ARRANGEDCRYSTALFORMATIONBUNNY,0,3,0,61, 0,100,0,0,0,0,0,70,1,0,0,0,0,0,14,@GOBJGUID+1,190502,0,0,0,0,0, 'Arranged Crystal Formation Bunny - Linked with Previous Event - Despawn Arranged Crystal formation'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN(19,20) AND `SourceGroup`=0 AND `SourceEntry`=12528; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(19,0,12528,0,8,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter completed in log'), +(20,0,12528,0,8,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter completed in log'), +(19,0,12528,1,9,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter taken in log'), +(20,0,12528,1,9,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter taken in log'), +(19,0,12528,2,28,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter rewarded'), +(20,0,12528,2,28,12654,0,0,0,0,'','Playing Along can be taken if player has quest part time hunter rewarded'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @PITCH; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@PITCH; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@PITCH; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@PITCH,0,0,0,9,0,100,0,5,30,9000,12000,11,54487,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Pitch - On Range - Cast Jump Attack'), +(@PITCH,0,1,0,0,0,100,0,5000,8000,7000,13000,11,24332,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Pitch - In Combat - Cast Rake'), +(@PITCH,0,2,0,11,0,100,0,0,0,0,0,45,1,1,0,0,0,0,9,@TRACKERGEKGEK,0,200,0,0,0,0, 'Pitch - On Spawn - Set Data Tracker Gekgek'), +(@PITCH,0,3,0,6,0,100,0,0,0,0,0,45,1,2,0,0,0,0,9,@TRACKERGEKGEK,0,200,0,0,0,0, 'Pitch - On Death - Set Data Tracker Gekgek'), +(@PITCH,0,4,0,4,0,100,0,0,0,0,0,45,1,3,0,0,0,0,9,@TRACKERGEKGEK,0,200,0,0,0,0, 'Pitch - On Aggro - Set Data Tracker Gekgek'), +(@PITCH,0,5,0,7,0,100,0,0,0,0,0,45,1,4,0,0,0,0,9,@TRACKERGEKGEK,0,200,0,0,0,0, 'Pitch - On Evade - Set Data Tracker Gekgek'); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= @TRACKERGEKGEK; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@TRACKERGEKGEK; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@TRACKERGEKGEK; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@TRACKERGEKGEK,0,0,0,0,0,100,0,3000,6000,4000,7000,11,50533,2,0,0,0,0,2,0,0,0,0,0,0,0, 'Tracker Gekgek - In Combat - Cast Flip Attack'), +(@TRACKERGEKGEK,0,1,2,38,0,100,0,1,1,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - On Data Set (Pitch Spawn 1 1) - Set Data 1 0'), +(@TRACKERGEKGEK,0,2,3,61,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Remove Quest Giver Flag'), +(@TRACKERGEKGEK,0,3,0,61,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Set Phase 2'), +(@TRACKERGEKGEK,0,4,5,38,0,100,0,1,2,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - On Data Set (Pitch Die 1 2) - Set Data 1 0'), +(@TRACKERGEKGEK,0,5,6,61,0,100,0,0,0,0,0,81,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Add Quest Giver Flag'), +(@TRACKERGEKGEK,0,6,7,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Say'), +(@TRACKERGEKGEK,0,7,0,61,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Set Phase 0'), +(@TRACKERGEKGEK,0,8,9,38,0,100,0,1,3,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - On Data Set (Pitch Aggro 1 3) - Set Data 1 0'), +(@TRACKERGEKGEK,0,9,10,61,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Say'), +(@TRACKERGEKGEK,0,10,0,61,0,100,0,0,0,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Set Phase 0'), +(@TRACKERGEKGEK,0,10,11,38,0,100,0,1,4,0,0,45,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - On Data Set (Pitch Evade 1 4) - Set Data 1 0'), +(@TRACKERGEKGEK,0,11,0,61,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - Linked with Previous Event- Say'), +(@TRACKERGEKGEK,0,12,0,10,2,100,0,1,100,30000,90000,1,2,2,0,0,0,0,1,0 ,0,0,0,0,0,0, 'Tracker Gekgek - On Los OOC - Say'), +(@TRACKERGEKGEK,0,13,0,11,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Tracker Gekgek - On Spawn - Set Phase 2'); + +DELETE FROM `creature_text` WHERE `entry` =@TRACKERGEKGEK; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@TRACKERGEKGEK,0,0, 'No! You steal kill! Now you owe Gekgek!', 12, 0, 100, 0, 0, 0, 'Tracker Gekgek'), +(@TRACKERGEKGEK,1,0, 'Dumb! Don''t shoot at it! Gekgek want trophy in one piece!', 12, 0, 100, 0, 0, 0, 'Tracker Gekgek'), +(@TRACKERGEKGEK,2,0, 'No let it get away! We got it this time.', 12, 0, 33, 0, 0, 0, 'Tracker Gekgek'), +(@TRACKERGEKGEK,2,1, 'Careful! No let it scratch you like last time.', 12, 0, 33, 0, 0, 0, 'Tracker Gekgek'), +(@TRACKERGEKGEK,2,2, 'Ahh! It''s coming right for us!', 12, 0, 34, 0, 0, 0, 'Tracker Gekgek'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI',`unit_flags`=`unit_flags`&~33554432 WHERE `entry` = @MOSSWALKERVICTIM; +UPDATE `creature` SET `MovementType` = 0, `spawndist`=0 WHERE `id` = @MOSSWALKERVICTIM; + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(28113,2811301,2811302); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@MOSSWALKERVICTIM,0,0,1,62,0,100,0,9728,0,0,0,87,(@MOSSWALKERVICTIM*100)+1,(@MOSSWALKERVICTIM*100)+2,(@MOSSWALKERVICTIM*100)+1,(@MOSSWALKERVICTIM*100)+2,(@MOSSWALKERVICTIM*100)+1,(@MOSSWALKERVICTIM*100)+2,1,0,0,0,0.0,0.0,0.0,0.0, 'Mosswalker Victim - On Gossip Select - Random Script Start'), +(@MOSSWALKERVICTIM,0,1,2,61,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0, 'Mosswalker Victim - Linked with Previous Event - Remove Gossip Flag'), +(@MOSSWALKERVICTIM,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0.0,0.0,0.0,0.0, 'Mosswalker Victim - Linked with Previous Event - Close Gossip'), +(@MOSSWALKERVICTIM,0,3,0,25,0,100,0,0,0,0,0,11,58806,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0, 'Mosswalker Victim - On Spawn - Cast Permament Feign Death on Self'), +((@MOSSWALKERVICTIM*100)+1,9,0,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 1 - Say'), +((@MOSSWALKERVICTIM*100)+1,9,1,0,0,0,100,0,2000,2000,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 1 - Die'), +((@MOSSWALKERVICTIM*100)+2,9,0,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 2 - Say'), +((@MOSSWALKERVICTIM*100)+2,9,1,0,0,0,100,0,1000,1000,0,0,85,52157,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Mosswalker Victim -Script 2 - Credit'), +((@MOSSWALKERVICTIM*100)+2,9,2,0,0,0,100,0,100,100,0,0,28,58806,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 2 - Remove Permament Feign Death'), +((@MOSSWALKERVICTIM*100)+2,9,3,0,0,0,100,0,15000,15000,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 2 - Set Invisible'), +((@MOSSWALKERVICTIM*100)+2,9,4,0,0,0,100,0,15500,15500,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mosswalker Victim - Script 2 - Die'); + +DELETE FROM `creature_text` WHERE `entry` = @MOSSWALKERVICTIM; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@MOSSWALKERVICTIM,0,0, 'Please take... my shinies. All done...', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,0,1, 'We not do anything... to them... I no understand.', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,0,2, 'Use my shinies... make weather good again... make undead things go away.', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,0,3, 'We gave shinies to shrine... we not greedy... why this happen?', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,0,4, 'I do something bad? I sorry...', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,1,0, 'We saved. You nice, dryskin.', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,1,1, 'Maybe you make weather better too?', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,1,2, 'You save us! Yay for you!', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'), +(@MOSSWALKERVICTIM,1,3, 'Thank you! You good!', 12, 0, 100, 0, 0, 0, 'Mosswalker Victim'); + +DELETE FROM `conditions` WHERE `SourceGroup`=9728 AND `SourceTypeOrReferenceId`=15 ; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry` ,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3` ,`ErrorTextId`,`ScriptName`,`Comment`) +VALUES (15,9728,0 ,0,9,12580,0 ,0,0 ,0, 'Only show gossip when quest player in on and has not completed the mosswalker saviour'); + +-- set correct previous quest for obtaining oracles or frenzyheart dailys, return of the lich hunter or return of the friendly dry skin not heros burden +UPDATE `quest_template` SET `PrevQuestId`=12695 WHERE `Id`IN(12735,12737,12736,12726,12761,12762,12705,12704); +UPDATE `quest_template` SET `PrevQuestId`=12692 WHERE `Id`IN(12703,12760,12759,12758,12734,12741,12732,12702); + +-- Pooling/grouping for Oracles/Frenzyheart Dailys +-- already exclusive grouped just not pooled +DELETE FROM `pool_quest` WHERE `pool_entry`=@QUESTPOOL; +INSERT INTO `pool_quest` (`entry`, `pool_entry`, `description`) VALUES +(12735, @QUESTPOOL, 'Oracle Soo-nee - A Cleansing Song'), +(12737, @QUESTPOOL, 'Oracle Soo-nee - Song of Fecundity'), +(12736, @QUESTPOOL, 'Oracle Soo-nee - Song of Reflection'), +(12726, @QUESTPOOL, 'Oracle Soo-nee - Song of Wind and Water'); +UPDATE `quest_template` SET `ExclusiveGroup`=12761 WHERE `Id`IN(12761,12762,12705); +DELETE FROM `pool_quest` WHERE `pool_entry`=@QUESTPOOL+1; +INSERT INTO `pool_quest` (`entry`, `pool_entry`, `description`) VALUES +(12761, @QUESTPOOL+1, 'Oracle Soo-dow - Mastery of the Crystals'), +(12762, @QUESTPOOL+1, 'Oracle Soo-dow - Power of the Great Ones'), +(12705, @QUESTPOOL+1, 'Oracle Soo-dow - Will of the Titans'); +DELETE FROM `pool_quest` WHERE `pool_entry`=@QUESTPOOL+2; +UPDATE `quest_template` SET `ExclusiveGroup`=12758 WHERE `Id`IN(12758,12734,12741,12732); +INSERT INTO `pool_quest` (`entry`, `pool_entry`, `description`) VALUES +(12758, @QUESTPOOL+2, 'Rejek - A Hero''s Headgear'), +(12734, @QUESTPOOL+2, 'Rejek - Rejek: First Blood'), +(12741, @QUESTPOOL+2, 'Rejek - Strength of the Tempest'), +(12732, @QUESTPOOL+2, 'Rejek - The Heartblood''s Strength'); +UPDATE `quest_template` SET `ExclusiveGroup`=12703 WHERE `Id`IN(12703,12760,12759); +DELETE FROM `pool_quest` WHERE `pool_entry`=@QUESTPOOL+3; +INSERT INTO `pool_quest` (`entry`, `pool_entry`, `description`) VALUES +(12703, @QUESTPOOL+3, 'Vekgar - Kartak''s Rampage'), +(12760, @QUESTPOOL+3, 'Vekgar - Secret Strength of the Frenzyheart'), +(12759, @QUESTPOOL+3, 'Vekgar - Tools of War'); +DELETE FROM `pool_template` WHERE `entry` BETWEEN @QUESTPOOL AND @QUESTPOOL+3; +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(@QUESTPOOL, 1, 'Oracle Soo-nee Dailies'), +(@QUESTPOOL+1, 1, 'Oracle Soo-dow Dailies'), +(@QUESTPOOL+2, 1, 'Rejek Dailies'), +(@QUESTPOOL+3, 1, 'Vekgar Dailies'); +-- Return of the lich hunter should be takable by both factions not only horde +UPDATE `quest_template` SET `RequiredRaces`=0 WHERE `Id`=12692; diff --git a/sql/updates/world/2013_04_05_01_world_misc.sql b/sql/updates/world/2013_04_05_01_world_misc.sql new file mode 100644 index 00000000000..816a4f5c0fa --- /dev/null +++ b/sql/updates/world/2013_04_05_01_world_misc.sql @@ -0,0 +1,91 @@ +SET @LAFOO := 28120; +SET @MOODLE := 28122; +SET @JALOOT := 28121; +SET @CHICKENESCAPEE := 28161; +SET @GOREGEK := 28214; +SET @DAJIK := 28215; +SET @ZEPIK := 28216; +SET @MISTWHISPERLIGHTNINGCLOUD := 28253; +SET @MISTWHISPERLIGHTNINGTARGET := 28254; +SET @GLINTINGDIRT := 28362; +SET @RHUNOK := 28416; +SET @TORMENTOR := 28575; +SET @SCAREDSOFTKNUCKLE := 50979; +SET @LIGHTNING := 51172; +SET @FRENZYAURA := 51234; +SET @MISTWHISPERAURA := 51239; +SET @DIGGINGFORTEASURE := 51405; +SET @TREASUREPING:= 51420; +SET @THROWSPEAR := 51603; +SET @CHAINS1 := 51606; +SET @CHAINS2 := 51607; +SET @RAINSPEAKERAURA := 51639; +SET @SPEARBORNAURA := 51642; +SET @MOSSWALKERAURA := 51644; +SET @SKYREACHPILLARAURA:= 51645; +SET @SAPPHIREHIVEAURA := 51651; +SET @WOLVARPING := 51791; +SET @GORLOCPING := 51794; +SET @CHICKENLOCATIONPING := 51843; +SET @SCAREDCHICKEN := 51846; +SET @DESSAWNRETAINER := 53163; + +DELETE FROM `creature_text` WHERE `entry`=@TORMENTOR; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@TORMENTOR,0,0,'Filthy $R intruder. DIE!',12,0,100,0,0,0,'Rhunok''s Tormentor'), +(@TORMENTOR,0,1,'If Rhunok regains his strength, we all die!',12,0,100,0,0,0,'Rhunok''s Tormentor'), +(@TORMENTOR,0,2,'There are intruders about. Slay them before they ruin everything!',12,0,100,0,0,0,'Rhunok''s Tormentor'), +(@TORMENTOR,0,3,'The bear god must be kept enfeebled so that the prophet can finish the ritual.',12,0,100,0,0,0,'Rhunok''s Tormentor'), +(@TORMENTOR,0,4,'Keep him weak!',12,0,100,0,0,0,'Rhunok''s Tormentor'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@TORMENTOR; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@TORMENTOR; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-113481,-113482,-113483,-113558,@TORMENTOR) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@TORMENTOR,0,0,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Rhunok''s Tormentor - On aggro - Say line'), +(@TORMENTOR,0,1,0,0,0,100,0,3000,8000,10000,20000,11,38556,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Rhunok''s Tormentor - On update IC - Spellcast Throw'), +(@TORMENTOR,0,2,0,0,0,100,0,5000,30000,30000,35000,11,54526,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Rhunok''s Tormentor - On update IC - Spellcast Torment'), +(@TORMENTOR,0,3,0,1,0,100,0,5000,30000,30000,40000,11,@THROWSPEAR,0,0,0,0,0,10,95460,@RHUNOK,0,0,0,0,0, 'Rhunok''s Tormentor - On update OOC - Spellcast Throw Spear'), + +(-113481,0,0,0,1,0,100,0,0,0,5000,5000,11,@CHAINS1,0,0,0,0,0,10,95460,@RHUNOK,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC - Spellcast Rhunok''s Chains'), +(-113482,0,0,0,1,0,100,0,0,0,5000,5000,11,@CHAINS2,0,0,0,0,0,10,95460,@RHUNOK,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC - Spellcast Rhunok''s Chains'), +(-113483,0,0,0,1,0,100,0,0,0,5000,5000,11,@CHAINS1,0,0,0,0,0,10,95460,@RHUNOK,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC - Spellcast Rhunok''s Chains'), +(-113558,0,0,0,1,0,100,0,0,0,5000,5000,11,@CHAINS2,0,0,0,0,0,10,95460,@RHUNOK,0,0,0,0,0, 'ELM General Purpose Bunny - On update OOC - Spellcast Rhunok''s Chains'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (@THROWSPEAR,@CHAINS1,@CHAINS2,@LIGHTNING,@SCAREDSOFTKNUCKLE,@FRENZYAURA,@RAINSPEAKERAURA,@WOLVARPING,@GORLOCPING,@DESSAWNRETAINER,@CHICKENLOCATIONPING,@TREASUREPING,@DIGGINGFORTEASURE,@MOSSWALKERAURA,@SPEARBORNAURA,@MISTWHISPERAURA,@SAPPHIREHIVEAURA,@SCAREDCHICKEN,@SKYREACHPILLARAURA); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,@LIGHTNING,0,31,3,@MISTWHISPERLIGHTNINGTARGET,0,0,0, '', 'Cloud to Lightning hits Mistwhisper Lightning Target'), +(13,1,@LIGHTNING,1,31,3,@MISTWHISPERLIGHTNINGCLOUD,0,0,0, '', 'Cloud to Lightning hits Mistwhisper Lightning Cloud'), +(13,1,@FRENZYAURA,0,31,3,@GOREGEK,0,0,0,'','Spell Frenzyheart Hill Aura targets Goregek the Bristlepine Hunter'), +(13,1,@FRENZYAURA,1,31,3,@DAJIK,0,0,0,'','Spell Frenzyheart Hill Aura targets Dajik the Wasp Hunter'), +(13,1,@FRENZYAURA,2,31,3,@ZEPIK,0,0,0,'','Spell Frenzyheart Hill Aura targets Zepik the Gorloc Hunter'), +(13,1,@RAINSPEAKERAURA,0,31,3,@LAFOO,0,0,0,'','Spell Rainspeaker Canopy Aura targets Lafoo'), +(13,1,@RAINSPEAKERAURA,1,31,3,@MOODLE,0,0,0,'','Spell Rainspeaker Canopy Aura targets Jaloot'), +(13,1,@RAINSPEAKERAURA,2,31,3,@JALOOT,0,0,0,'','Spell Rainspeaker Canopy Aura targets Moodle'), +(13,1,@WOLVARPING,0,31,3,@GOREGEK,0,0,0,'','Spell Wolvar Location Ping targets Goregek the Bristlepine Hunter'), +(13,1,@WOLVARPING,1,31,3,@DAJIK,0,0,0,'','Spell Wolvar Location Ping targets Dajik the Wasp Hunter'), +(13,1,@WOLVARPING,2,31,3,@ZEPIK,0,0,0,'','Spell Wolvar Location Ping targets Zepik the Gorloc Hunter'), +(13,1,@GORLOCPING,0,31,3,@LAFOO,0,0,0,'','Spell Gorloc Location Ping targets Lafoo'), +(13,1,@GORLOCPING,1,31,3,@JALOOT,0,0,0,'','Spell Gorloc Location Ping targets Jaloot'), +(13,1,@GORLOCPING,2,31,3,@MOODLE,0,0,0,'','Spell Gorloc Location Ping targets Moodle'), +(13,1,@DESSAWNRETAINER,0,31,3,@LAFOO,0,0,0,'','Spell Dessawn Retainer targets Lafoo'), +(13,1,@DESSAWNRETAINER,1,31,3,@DAJIK,0,0,0,'','Spell Dessawn Retainer targets Dajik the Wasp Hunter'), +(13,1,@DESSAWNRETAINER,2,31,3,@ZEPIK,0,0,0,'','Spell Dessawn Retainer targets Zepik the Gorloc Hunter'), +(13,1,@DESSAWNRETAINER,3,31,3,@JALOOT,0,0,0,'','Spell Dessawn Retainer targets Jaloot '), +(13,1,@DESSAWNRETAINER,4,31,3,@MOODLE,0,0,0,'','Spell Dessawn Retainer targets Moodle'), +(13,1,@DESSAWNRETAINER,5,31,3,@GOREGEK,0,0,0,'','Spell Dessawn Retainer targets Goregek'), +(13,1,@TREASUREPING,0,31,3,@LAFOO,0,0,0,'','Spell Dessawn Retainer targets Lafoo'), +(13,1,@TREASUREPING,1,31,3,@JALOOT,0,0,0,'','Spell Dessawn Retainer targets Jaloot '), +(13,1,@TREASUREPING,2,31,3,@MOODLE,0,0,0,'','Spell Dessawn Retainer targets Moodle'), +(13,1,@CHICKENLOCATIONPING,0,31,3,@GOREGEK,0,0,0,'','Spell chicken ping targets Goregek'), +(13,1,@CHICKENLOCATIONPING,1,31,3,@DAJIK,0,0,0,'','Spell chicken ping targets Dajik '), +(13,1,@CHICKENLOCATIONPING,2,31,3,@ZEPIK,0,0,0,'','Spell chicken ping targets Zepik'), +(13,3,@SCAREDCHICKEN,0,31,3,@CHICKENESCAPEE,0,0,0,'','Scared Chicken targets only chicken escapee'), +(13,1,@MOSSWALKERAURA,0,31,3,@MOODLE,0,0,0,'','Mosswalker village aura targets moodle'), +(13,1,@SPEARBORNAURA,0,31,3,@JALOOT,0,0,0,'','spearborn encampment aura targets moodle'), +(13,1,@MISTWHISPERAURA,0,31,3,@ZEPIK,0,0,0,'','mistwhisper refuge aura targets zepik'), +(13,1,@SAPPHIREHIVEAURA,0,31,3,@DAJIK,0,0,0,'','sapphire hive aura targets dajik'), +(13,1,@THROWSPEAR,0,31,3,@RHUNOK,0,0,0,'','Spell Throw Spear targets Rhunok'), +(13,1,@CHAINS1,0,31,3,@RHUNOK,0,0,0,'','Spell Rhunok''s Chains targets Rhunok'), +(13,1,@CHAINS2,0,31,3,@RHUNOK,0,0,0,'','Spell Rhunok''s Chains targets Rhunok'), +(13,1,@SKYREACHPILLARAURA,0,31,3,@DAJIK,0,0,0,'','skyreach pillar aura targets dajik'); diff --git a/sql/updates/world/2013_04_05_02_world_creature_ai_scripts.sql b/sql/updates/world/2013_04_05_02_world_creature_ai_scripts.sql new file mode 100644 index 00000000000..311ae1781f8 --- /dev/null +++ b/sql/updates/world/2013_04_05_02_world_creature_ai_scripts.sql @@ -0,0 +1 @@ +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=28371; diff --git a/sql/updates/world/2013_04_06_00_world_quest_template.sql b/sql/updates/world/2013_04_06_00_world_quest_template.sql new file mode 100644 index 00000000000..ebd4ad2ffcc --- /dev/null +++ b/sql/updates/world/2013_04_06_00_world_quest_template.sql @@ -0,0 +1,10 @@ +UPDATE `quest_template` SET `NextQuestId`=12931,`NextQuestIdChain`=12931 WHERE `Id`=12930; +UPDATE `quest_template` SET `PrevQuestId`=12930,`ExclusiveGroup`=-12931 WHERE `Id` IN (12931,12937); +UPDATE `quest_template` SET `PrevQuestId`=12931,`ExclusiveGroup`=-12957 WHERE `Id` IN (12957,12964); +UPDATE `quest_template` SET `PrevQuestId`=12957,`ExclusiveGroup`=-12965 WHERE `Id` IN (12965,12978); +UPDATE `quest_template` SET `NextQuestId`=12984 WHERE `Id`=12980; +UPDATE `quest_template` SET `PrevQuestId`=12980,`NextQuestId`=12988 WHERE `Id`=12984; +UPDATE `quest_template` SET `ExclusiveGroup`=-12988 WHERE `Id`=12988; +UPDATE `quest_template` SET `PrevQuestId`=12984,`ExclusiveGroup`=-12988 WHERE `Id`=12991; +UPDATE `quest_template` SET `PrevQuestId`=12988,`NextQuestId`=12998 WHERE `Id` =12993; +UPDATE `quest_template` SET `PrevQuestId`=12993,`NextQuestIdChain`=13007 WHERE `Id` =12998; diff --git a/sql/updates/world/2013_04_06_01_world_npc_trainer.sql b/sql/updates/world/2013_04_06_01_world_npc_trainer.sql new file mode 100644 index 00000000000..b975f29d8c8 --- /dev/null +++ b/sql/updates/world/2013_04_06_01_world_npc_trainer.sql @@ -0,0 +1,4 @@ +-- Add Enchant Boots - Lesser Accuracy to appropriate trainers +DELETE FROM `npc_trainer` WHERE `spell`=63746; +INSERT INTO `npc_trainer` (`entry`,`spell`,`spellcost`,`reqskill`,`reqskillvalue`,`reqlevel`) VALUES +(201009,63746,5000,333,225,0); diff --git a/sql/updates/world/2013_04_06_02_world_creature.sql b/sql/updates/world/2013_04_06_02_world_creature.sql new file mode 100644 index 00000000000..e2658210522 --- /dev/null +++ b/sql/updates/world/2013_04_06_02_world_creature.sql @@ -0,0 +1,39 @@ +SET @GUID := 110224; +SET @DIRT := 28362; + +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+33; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`MovementType`) VALUES +(@GUID+0 ,@DIRT,571,1,1,0,5652.974,4494.586,-136.6679,2.600541,300,0,0), +(@GUID+1 ,@DIRT,571,1,1,0,5682.897,4479.211,-135.6831,4.817109,300,0,0), +(@GUID+2 ,@DIRT,571,1,1,0,5616.783,4507.514,-136.2347,2.792527,300,0,0), +(@GUID+3 ,@DIRT,571,1,1,0,5566.848,4608.069,-140.0046,0.08726646,300,0,0), +(@GUID+4 ,@DIRT,571,1,1,0,5726.52,4535.192,-138.999,1.256637,300,0,0), +(@GUID+5 ,@DIRT,571,1,1,0,5693.346,4629.685,-138.3224,4.921828,300,0,0), +(@GUID+6 ,@DIRT,571,1,1,0,5733.776,4598.793,-134.9071,0.8028514,300,0,0), +(@GUID+7 ,@DIRT,571,1,1,0,5752.648,4496.542,-132.4478,4.886922,300,0,0), +(@GUID+8 ,@DIRT,571,1,1,0,5705.064,4435.867,-141.0292,5.986479,300,0,0), +(@GUID+9 ,@DIRT,571,1,1,0,5736.984,4459.437,-134.9569,1.291544,300,0,0), +(@GUID+10,@DIRT,571,1,1,0,5579.51,4442.721,-139.8728,5.5676,300,0,0), +(@GUID+11,@DIRT,571,1,1,0,5726.514,4370.49,-138.5187,3.106686,300,0,0), +(@GUID+12,@DIRT,571,1,1,0,5801.268,4529.366,-134.282,3.228859,300,0,0), +(@GUID+13,@DIRT,571,1,1,0,5806.822,4481.874,-131.8635,4.607669,300,0,0), +(@GUID+14,@DIRT,571,1,1,0,5868.016,4498.958,-133.2091,3.525565,300,0,0), +(@GUID+15,@DIRT,571,1,1,0,5865.933,4563.596,-133.3011,3.525565,300,0,0), +(@GUID+16,@DIRT,571,1,1,0,5847.393,4599.288,-136.0588,5.532694,300,0,0), +(@GUID+17,@DIRT,571,1,1,0,5768.064,4605.938,-137.6851,3.874631,300,0,0), +(@GUID+18,@DIRT,571,1,1,0,5743.717,4645.34,-135.1314,3.071779,300,0,0), +(@GUID+19,@DIRT,571,1,1,0,5789.393,4640.829,-135.5909,5.532694,300,0,0), +(@GUID+20,@DIRT,571,1,1,0,5906.656,4612.754,-132.0416,2.600541,300,0,0), +(@GUID+21,@DIRT,571,1,1,0,5842.542,4682.008,-134.9288,4.677482,300,0,0), +(@GUID+22,@DIRT,571,1,1,0,5822.073,4726.694,-132.8639,6.195919,300,0,0), +(@GUID+23,@DIRT,571,1,1,0,5917.018,4735.479,-137.8103,1.43117,300,0,0), +(@GUID+24,@DIRT,571,1,1,0,5863.843,4759.619,-131.9068,5.166174,300,0,0), +(@GUID+25,@DIRT,571,1,1,0,5656.485,4679.363,-132.4746,0.8552113,300,0,0), +(@GUID+26,@DIRT,571,1,1,0,5699.089,4671.949,-135.4732,5.986479,300,0,0), +(@GUID+27,@DIRT,571,1,1,0,5731.342,4688.484,-134.2571,3.438299,300,0,0), +(@GUID+28,@DIRT,571,1,1,0,5760.655,4690.131,-134.4649,5.585053,300,0,0), +(@GUID+29,@DIRT,571,1,1,0,5677.118,4725.341,-135.5663,3.577925,300,0,0), +(@GUID+30,@DIRT,571,1,1,0,5704.706,4763.644,-137.0218,5.009095,300,0,0), +(@GUID+31,@DIRT,571,1,1,0,5751.76,4767.774,-134.9354,3.979351,300,0,0), +(@GUID+32,@DIRT,571,1,1,0,5786.583,4751.955,-133.6232,0.7679449,300,0,0), +(@GUID+33,@DIRT,571,1,1,0,5807.025,4767.91,-134.8856,3.560472,300,0,0); diff --git a/sql/updates/world/2013_04_06_03_world_misc.sql b/sql/updates/world/2013_04_06_03_world_misc.sql new file mode 100644 index 00000000000..6cc441d9e5a --- /dev/null +++ b/sql/updates/world/2013_04_06_03_world_misc.sql @@ -0,0 +1,25 @@ +DELETE FROM `gameobject_loot_template` WHERE `entry`=24320 AND `item` IN (38340,38341,38397); +DELETE FROM `gameobject_loot_template` WHERE `entry`=24326 AND `item`=38397; +DELETE FROM `gameobject_loot_template` WHERE `entry`=24330 AND `item`=38335; +DELETE FROM `gameobject_loot_template` WHERE `entry`=25028 AND `item`=38337; + +UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=100 WHERE `entry` BETWEEN 24319 AND 24340; +UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=100 WHERE `entry` IN (25026,25027,25028); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (51060,51068,51088,51094); +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(51060,51226,1,'On spellhit Have Withered Batwing - Spellcast Withered Batwing Kill Credit'), +(51068,51227,1,'On spellhit Have Muddy Mire Maggot - Spellcast Muddy Mire Maggot Kill Credit'), +(51088,51228,1,'On spellhit Have Amberseed - Spellcast Amberseed Kill Credit'), +(51094,51229,1,'On spellhit Have Chilled Serpent Mucus - Spellcast Chilled Serpent Mucus Kill Credit'); + +DELETE FROM `spell_dbc` WHERE `Id`=50574; +INSERT INTO `spell_dbc` (`Id`,`Attributes`,`CastingTimeIndex`,`ProcChance`,`RangeIndex`,`EquippedItemClass`,`Effect1`,`EffectMiscValue1`,`EffectImplicitTargetA1`,`SchoolMask`,`Comment`) VALUES +(50574,256,1,101,11,-1,90,28042,25,1,'Captain Brandon Kill Credit'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9668 AND `SourceEntry` IN (13098,13119); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9668 AND `SourceEntry`=0; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,9668,13098,0,9,12587,0,0,0,'','Alchemist Finklestein - Show different gossip if player has taken quest Troll Patrol'), +(14,9668,13119,0,9,12541,0,0,0,'','Alchemist Finklestein - Show different gossip if player has taken quest Troll Patrol: The Alchemist''s Apprentice'), +(15,9668,0,0,9,12541,0,0,0,'','Alchemist Finklestein - Show gossip option only if player has taken quest Troll Patrol: The Alchemist''s Apprentice'); diff --git a/sql/updates/world/2013_04_07_00_world_areatrigger_teleport.sql b/sql/updates/world/2013_04_07_00_world_areatrigger_teleport.sql new file mode 100644 index 00000000000..b9669aaf9c0 --- /dev/null +++ b/sql/updates/world/2013_04_07_00_world_areatrigger_teleport.sql @@ -0,0 +1,27 @@ +DELETE FROM `areatrigger_teleport` WHERE `id` IN (4917, 4919, 4921, 4922, 4923, 4924, 4925, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4941, 4944, 5326, 5328, 5329, 5330, 5331, 5447); +INSERT INTO `areatrigger_teleport` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`, `name`) VALUES +(4917, 559, 4054.57, 2923.23, 13.8179, 0, 'Arena - Nagrand - Teleport Target - Game On'), +(4919, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4921, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4922, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4923, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4924, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4925, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(4927, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4928, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4929, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4930, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4931, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4932, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4933, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4934, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4935, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4936, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4941, 572, 1286.57, 1667.4, 39.602, 0, 'Arena - Undercity - Teleport Target - Game On'), +(4944, 562, 6238.89, 264.155, 0.894302, 0, 'Arena - Bladesedge - Teleport Target - Game On'), +(5326, 617, 1291.57, 792.965, 8.11463, 0, 'Arena - Dalaran Arena - Teleport Target'), +(5328, 617, 1291.57, 792.965, 8.11463, 0, 'Arena - Dalaran Arena - Teleport Target'), +(5329, 617, 1291.57, 792.965, 8.11463, 0, 'Arena - Dalaran Arena - Teleport Target'), +(5330, 617, 1291.57, 792.965, 8.11463, 0, 'Arena - Dalaran Arena - Teleport Target'), +(5331, 617, 1291.57, 792.965, 8.11463, 0, 'Arena - Dalaran Arena - Teleport Target'), +(5447, 618, 763.365, -284.29, 28.2767, 0, 'Arena - Orgrimmar - Teleport Target 3'); diff --git a/sql/updates/world/2013_04_08_00_world_areatrigger_teleport.sql b/sql/updates/world/2013_04_08_00_world_areatrigger_teleport.sql new file mode 100644 index 00000000000..10e1668136c --- /dev/null +++ b/sql/updates/world/2013_04_08_00_world_areatrigger_teleport.sql @@ -0,0 +1,14 @@ +DELETE FROM `areatrigger_teleport` WHERE `id` IN (5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138); +INSERT INTO `areatrigger_teleport` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`, `name`) VALUES +(5127, 0, 2462.76, -5598.19, 550.22, 3.66519, 'Ebon Hold (E.K.) Top Return Target'), +(5128, 0, 2472.67, -5530.1, 420.642, 4.50295, 'Ebon Hold (E.K.) Top West Target'), +(5129, 0, 2462.76, -5598.19, 550.22, 3.66519, 'Ebon Hold (E.K.) Top Return Target'), +(5130, 0, 2397.37, -5581.06, 420.643, 6.07375, 'Ebon Hold (E.K.) Top South Target'), +(5131, 0, 2462.76, -5598.19, 550.22, 3.66519, 'Ebon Hold (E.K.) Top Return Target'), +(5132, 0, 2522.45, -5605.7, 420.642, 2.94961, 'Ebon Hold (E.K.) Top North Target'), +(5133, 0, 2462.76, -5598.19, 550.22, 3.66519, 'Ebon Hold (E.K.) Top Return Target'), +(5134, 0, 2448.02, -5655.82, 420.643, 1.3439, 'Ebon Hold (E.K.) Top East Target'), +(5135, 0, 2435.77, -5610.34, 366.82, 0.610865, 'Ebon Hold (E.K.) Middle -> Bottom Target'), +(5136, 0, 2435.77, -5610.34, 366.82, 0.610865, 'Ebon Hold (E.K.) Middle -> Bottom Target'), +(5137, 0, 2472.9, -5530.64, 420.643, 4.45059, 'Ebon Hold (E.K.) Bottom -> Middle Target'), +(5138, 0, 2415.16, -5733.04, 153.922, 3.64774, 'Ebon Hold (E.K.) Bottom -> Ground Target'); diff --git a/sql/updates/world/2013_04_11_00_world_misc.sql b/sql/updates/world/2013_04_11_00_world_misc.sql new file mode 100644 index 00000000000..53e2ffcb716 --- /dev/null +++ b/sql/updates/world/2013_04_11_00_world_misc.sql @@ -0,0 +1,168 @@ +SET @NPC_URSOC := 26633; +SET @NPC_RAGEPAW := 27328; +SET @NPC_SPIRIT := 27373; +SET @NPC_BLOOD := 28854; + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=9496 AND `id`=0; +DELETE FROM `gossip_menu_option` WHERE `menu_id`=9497 AND `id` IN (0,1,2); +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(9496,0,0, 'We have the purified ashes of Vordrassil''s sapling. If we can subdue Ursoc, we might be able to heal his soul.',1,1,9497,0,0,0, ''), +(9497,0,0, 'Assume your druidic bear form, Tur.',1,1,0,0,0,0, ''), +(9497,1,0, 'Help us subdue him.',1,1,0,0,0,0, ''), +(9497,2,0, 'We could use a healer.',1,1,0,0,0,0, ''); + +DELETE FROM `gossip_menu` WHERE `entry`=9496 AND `text_id`=12785; +DELETE FROM `gossip_menu` WHERE `entry`=9497 AND `text_id`=12787; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9496,12785), +(9497,12787); + +UPDATE `creature_template` SET `faction_A`=16, `faction_H`=16, `dmg_multiplier`=4.6, `unit_flags`=32832 WHERE `entry`=@NPC_URSOC; +UPDATE `creature_template` SET `gossip_menu_id`=9496, `speed_walk`=0.666667, `speed_run`=0.992063 WHERE `entry`=@NPC_RAGEPAW; +UPDATE `creature_template` SET `speed_run`=0.357143 WHERE `entry`=@NPC_BLOOD; + +UPDATE `creature_model_info` SET `bounding_radius`=3.666, `combat_reach`=9 WHERE `modelid`=23964; + +DELETE FROM `creature_template_addon` WHERE `entry`=28854; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES +(28854,1,'52561'); + +UPDATE `creature` SET `spawntimesecs`=0 WHERE `guid` IN (104065,104066,114077); + +DELETE FROM `creature_addon` WHERE `guid` IN (104065,104066,104068,104069,104070,104071); +INSERT INTO `creature_addon` (`guid`,`auras`) VALUES +(104065,'16245'), +(104066,'16245'), +(104068,'16245'), +(104069,'16245'), +(104070,'16245'), +(104071,'16245'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (48398,48399); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9496 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry` IN (52551,52554); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=@NPC_RAGEPAW; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,48398,0,0,31,0,3,24921,0,0,'','Spell Tur''s Chains targets Cosmetic Trigger - LAB'), +(13,1,48398,0,0,29,0,@NPC_RAGEPAW,2,0,0,'','Spell Tur''s Chains target needs to be within 2y of Tur Ragepaw'), +(13,1,48399,0,0,31,0,3,24921,0,0,'','Spell Tur''s Chains targets Cosmetic Trigger - LAB'), +(13,1,48399,0,0,29,0,@NPC_RAGEPAW,2,0,0,'','Spell Tur''s Chains target needs to be within 2y of Tur Ragepaw'), +(15,9496,0,0,0,9,0,12236,0,0,0,'','Tur Ragepaw - Show gossip option only if player has taken quest Ursoc, the Bear God'), +(15,9496,0,0,1,9,0,12249,0,0,0,'','Tur Ragepaw - Show gossip option only if player has taken quest Ursoc, the Bear God'), +(17,0,52551,0,0,38,1,80,4,0,0,'','Spell Lifebloom will be casted only if target has less than 80% health'), +(17,0,52554,0,0,38,1,65,4,0,0,'','Spell Nourish will be casted only if target has less than 65% health'), +(22,14,@NPC_RAGEPAW,0,0,1,1,48368,1,0,0,'','SAI of Tur Ragepaw triggers only if under the effect of aura Bearform'), +(22,16,@NPC_RAGEPAW,0,0,1,1,48369,1,0,0,'','SAI of Tur Ragepaw triggers only if under the effect of aura Moonkin Form'), +(22,17,@NPC_RAGEPAW,0,0,1,1,48371,1,0,0,'','SAI of Tur Ragepaw triggers only if under the effect of aura Tree of Life'); + +DELETE FROM `creature_text` WHERE `entry` IN (@NPC_RAGEPAW,@NPC_SPIRIT); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_RAGEPAW,0,0, 'Stay behind me, $r. I will do my best to protect you.',12,0,100,0,0,0, 'Tur Ragepaw'), +(@NPC_RAGEPAW,1,0, 'My freedom means nothing if we fail to save Ursoc. Make haste, $N.',12,0,100,0,0,0, 'Tur Ragepaw'), +(@NPC_RAGEPAW,2,0, 'I will watch over you and your allies, $r.',12,0,100,0,0,0, 'Tur Ragepaw'), +(@NPC_RAGEPAW,3,0, 'Ursoc, brother of Ursol and guardian of the furbolg tribes... show yourself!',12,0,100,0,0,0, 'Tur Ragepaw'), +(@NPC_SPIRIT,0,0, 'I thank you all. The druids of old were wise to tear down Vordrassil, for its roots seep deep into the dwelling of an ancient evil.',12,0,100,0,0,0, 'Spirit of Ursoc'), +(@NPC_SPIRIT,1,0, 'You know their kind as old gods. Beware Yogg-Saron, the beast with a thousand maws. His evil extends beyond Vordrassil''s roots.',12,0,100,0,0,0, 'Spirit of Ursoc'); + +DELETE FROM `waypoints` WHERE `entry`=@NPC_RAGEPAW; +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(@NPC_RAGEPAW, 1, 4688.4, -3854.87, 327.0471, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 2, 4705.639, -3845.388, 327.5565, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 3, 4726.497, -3846.529, 330.2256, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 4, 4743.628, -3848.904, 332.7676, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 5, 4756.063, -3847.442, 333.9136, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 6, 4782.305, -3843.417, 333.9443, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 7, 4813.348, -3838.03, 336.6674, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 8, 4835.112, -3837.782, 338.4213, 'Tur Ragepaw'), +(@NPC_RAGEPAW, 9, 4865.375, -3842.427, 338.2963, 'Tur Ragepaw'); + +DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (@NPC_URSOC,@NPC_BLOOD); +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (@NPC_URSOC,@NPC_RAGEPAW,@NPC_SPIRIT,@NPC_BLOOD); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-104065,-104066,-104068,-104069,-104070,-104071,@NPC_URSOC,@NPC_RAGEPAW,@NPC_SPIRIT,@NPC_BLOOD) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_RAGEPAW*100+0,@NPC_RAGEPAW*100+1,@NPC_RAGEPAW*100+2,@NPC_RAGEPAW*100+3,@NPC_SPIRIT*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-104068,0,0,0,38,0,100,0,0,1,0,0,11,48399,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104068,0,1,0,38,0,100,0,0,2,0,0,11,48334,0,0,0,0,0,19,@NPC_RAGEPAW,20,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104069,0,0,0,38,0,100,0,0,1,0,0,11,48398,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104069,0,1,0,38,0,100,0,0,2,0,0,11,48334,0,0,0,0,0,19,@NPC_RAGEPAW,20,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104070,0,0,0,38,0,100,0,0,1,0,0,11,48399,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104070,0,1,0,38,0,100,0,0,2,0,0,11,48334,0,0,0,0,0,19,@NPC_RAGEPAW,20,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104071,0,0,0,38,0,100,0,0,1,0,0,11,48398,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104071,0,1,0,38,0,100,0,0,2,0,0,11,48334,0,0,0,0,0,19,@NPC_RAGEPAW,20,0,0,0,0,0,'Cosmetic Trigger - LAB - On data 0 1 set - Spellcast Tur''s Chains'), +(-104065,0,0,0,8,0,100,0,48399,0,0,0,69,1,0,0,0,0,0,8,0,0,0,4672.254,-3872.959,327.6967,0,'Cosmetic Trigger - LAB - On spellhit Tur''s Chains - Move to position'), +(-104065,0,1,0,34,0,100,0,0,1,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On movement inform - Despawn'), +(-104066,0,0,0,8,0,100,0,48398,0,0,0,69,1,0,0,0,0,0,8,0,0,0,4677.567,-3874.965,323.9017,0,'Cosmetic Trigger - LAB - On spellhit Tur''s Chains - Move to position'), +(-104066,0,1,0,34,0,100,0,0,1,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cosmetic Trigger - LAB - On movement inform - Despawn'), + +(@NPC_URSOC,0,0,0,54,0,100,0,0,0,0,0,5,53,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ursoc - Just summoned - Play emote'), +(@NPC_URSOC,0,1,0,0,0,100,0,7000,8000,20000,20000,11,52560,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ursoc - On update IC - Spellcast Summon Blood of the Old God'), +(@NPC_URSOC,0,2,0,0,0,100,0,10000,13000,21000,25000,11,52583,0,0,0,0,0,18,50,0,0,0,0,0,0,'Ursoc - On update IC - Spellcast Old God''s Influence'), +(@NPC_URSOC,0,3,0,9,0,100,0,0,5,9000,12000,11,52581,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ursoc - On target within 5y - Spellcast Crunch Armor'), +(@NPC_URSOC,0,4,0,8,0,100,0,48549,0,0,0,12,@NPC_SPIRIT,3,25000,0,0,0,1,0,0,0,0,0,0,0,'Ursoc - On spellhit Ashes of Vordrassil - Summon Spirit of Ursoc'), +(@NPC_URSOC,0,5,0,6,0,100,0,0,0,0,0,45,0,1,0,0,0,0,10,114077,@NPC_RAGEPAW,0,0,0,0,0,'Ursoc - On death - Set data 0 1 Tur Ragepaw'), + +(@NPC_RAGEPAW,0,0,1,11,0,100,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On spawn - Set faction default'), +(@NPC_RAGEPAW,0,1,2,61,0,100,0,0,0,0,0,45,0,2,0,0,0,0,9,24921,2,20,0,0,0,0,'Tur Ragepaw - On spawn - Set data 0 2 Cosmetic Trigger - LAB'), +(@NPC_RAGEPAW,0,2,3,61,0,100,0,0,0,0,0,90,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On spawn - Set unit_field_bytes1 (kneel)'), +(@NPC_RAGEPAW,0,3,4,61,0,100,0,0,0,0,0,82,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On spawn - Set npcflag gossip'), +(@NPC_RAGEPAW,0,4,0,61,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On spawn - Set reaction defensive'), +(@NPC_RAGEPAW,0,5,8,62,0,100,0,9497,0,0,0,80,@NPC_RAGEPAW*100+0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On gossip select - Run script 0'), +(@NPC_RAGEPAW,0,6,8,62,0,100,0,9497,1,0,0,80,@NPC_RAGEPAW*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On gossip select - Run script 1'), +(@NPC_RAGEPAW,0,7,8,62,0,100,0,9497,2,0,0,80,@NPC_RAGEPAW*100+2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On gossip select - Run script 2'), +(@NPC_RAGEPAW,0,8,9,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Tur Ragepaw - On gossip select - Close gossip'), +(@NPC_RAGEPAW,0,9,10,61,0,100,0,0,0,0,0,83,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On gossip select - Remove npcflag gossip'), +(@NPC_RAGEPAW,0,10,0,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,9,24921,2,20,0,0,0,0,'Tur Ragepaw - On gossip select - Set data 0 1 Cosmetic Trigger - LAB'), +(@NPC_RAGEPAW,0,11,0,38,0,100,0,0,1,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On data 0 1 set - Despawn'), +(@NPC_RAGEPAW,0,12,0,40,0,100,0,9,@NPC_RAGEPAW,0,0,80,@NPC_RAGEPAW*100+3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On WP 9 Reached - Run script 3'), +(@NPC_RAGEPAW,0,13,14,25,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On reset - Set event phase 1'), +(@NPC_RAGEPAW,0,14,0,61,0,100,0,0,0,0,0,28,52507,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On reset - Remove aura Ragepaw''s Presence'), +(@NPC_RAGEPAW,0,15,0,25,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On reset - Set event phase 2'), +(@NPC_RAGEPAW,0,16,0,25,0,100,0,0,0,0,0,22,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On reset - Set event phase 3'), +(@NPC_RAGEPAW,0,17,0,4,1,100,0,0,0,0,0,11,52507,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On aggro (phase 1) - Spellcast Ragepaw''s Presence'), +(@NPC_RAGEPAW,0,18,0,9,1,100,0,0,5,2500,4000,11,52504,0,0,0,0,0,2,0,0,0,0,0,0,0,'Tur Ragepaw - On target within 5y (phase 1) - Spellcast Lacerate'), +(@NPC_RAGEPAW,0,19,0,9,1,100,0,0,5,6000,8000,11,52506,0,0,0,0,0,2,0,0,0,0,0,0,0,'Tur Ragepaw - On target within 5y (phase 1) - Spellcast Maul'), +(@NPC_RAGEPAW,0,20,0,14,1,100,0,2000,30,20000,20000,11,6795,0,0,0,0,0,2,0,0,0,0,0,0,0,'Tur Ragepaw - On friendly attacked (phase 1) - Spellcast Growl'), +(@NPC_RAGEPAW,0,21,0,4,2,100,0,0,0,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On aggro (phase 2) - Stop combat movement'), +(@NPC_RAGEPAW,0,22,0,9,2,100,0,0,40,2500,4000,11,52501,0,0,0,0,0,2,0,0,0,0,0,0,0,'Tur Ragepaw - On target within 40y (phase 2) - Spellcast Wrath'), +(@NPC_RAGEPAW,0,23,0,9,2,100,0,0,40,13000,14000,11,52502,0,0,0,0,0,2,0,0,0,0,0,0,0,'Tur Ragepaw - On target within 40y (phase 2) - Spellcast Moonfire'), +(@NPC_RAGEPAW,0,24,0,0,4,100,0,0,0,1500,1500,11,52554,0,0,0,0,0,18,40,0,0,0,0,0,0,'Tur Ragepaw - On update IC (phase 4) - Spellcast Nourish'), +(@NPC_RAGEPAW,0,25,0,0,4,100,0,50,50,1700,1700,11,52551,0,0,0,0,0,18,40,0,0,0,0,0,0,'Tur Ragepaw - On update IC (phase 4) - Spellcast Lifebloom'), +(@NPC_RAGEPAW,0,26,0,4,4,100,0,0,0,0,0,8,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw - On aggro (phase 4) - Set reaction aggressive'), + +(@NPC_SPIRIT,0,0,0,54,0,100,0,0,0,0,0,80,@NPC_SPIRIT*100,2,0,0,0,0,1,0,0,0,0,0,0,0,'Spirit of Ursoc - Just summoned - Run script'), + +(@NPC_BLOOD,0,0,0,9,0,100,1,0,1.5,0,0,11,52564,0,0,0,0,0,1,0,0,0,0,0,0,0,'Blood of the Old God - On target within 1.5y - Spellcast Corruption of the Old God'), + +(@NPC_RAGEPAW*100+0,9,0,0,0,0,100,0,0,0,0,0,11,48368,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Spellcast Bearform'), +(@NPC_RAGEPAW*100+0,9,1,0,0,0,100,0,300,300,0,0,2,250,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Set faction'), +(@NPC_RAGEPAW*100+0,9,2,0,0,0,100,0,0,0,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Remove unit_field_bytes1 (kneel)'), +(@NPC_RAGEPAW*100+0,9,3,0,0,0,100,0,2500,2500,0,0,1,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Say line'), +(@NPC_RAGEPAW*100+0,9,4,0,0,0,100,0,4700,4700,0,0,53,1,@NPC_RAGEPAW,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Start WP movement'), +(@NPC_RAGEPAW*100+0,9,6,0,0,0,100,0,0,0,0,0,8,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Set reaction aggressive'), +(@NPC_RAGEPAW*100+0,9,5,0,0,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 0 - Set event phase 1'), + +(@NPC_RAGEPAW*100+1,9,0,0,0,0,100,0,0,0,0,0,11,48369,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Spellcast Moonkin Form'), +(@NPC_RAGEPAW*100+1,9,1,0,0,0,100,0,300,300,0,0,2,250,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Set faction'), +(@NPC_RAGEPAW*100+1,9,2,0,0,0,100,0,0,0,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Remove unit_field_bytes1 (kneel)'), +(@NPC_RAGEPAW*100+1,9,3,0,0,0,100,0,0,0,0,0,11,24905,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Spellcast Moonkin Form (Passive)'), +(@NPC_RAGEPAW*100+1,9,4,0,0,0,100,0,0,0,0,0,11,24907,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Spellcast Moonkin Aura'), +(@NPC_RAGEPAW*100+1,9,5,0,0,0,100,0,400,400,0,0,11,52503,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Spellcast Empowered Moonkin Aura'), +(@NPC_RAGEPAW*100+1,9,6,0,0,0,100,0,2500,2500,0,0,1,1,0,0,0,0,0,7,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Say line'), +(@NPC_RAGEPAW*100+1,9,7,0,0,0,100,0,4700,4700,0,0,53,1,@NPC_RAGEPAW,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Start WP movement'), +(@NPC_RAGEPAW*100+1,9,8,0,0,0,100,0,0,0,0,0,8,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Set reaction aggressive'), +(@NPC_RAGEPAW*100+1,9,9,0,0,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 1 - Set event phase 2'), + +(@NPC_RAGEPAW*100+2,9,0,0,0,0,100,0,0,0,0,0,11,48371,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Spellcast Tree of Life'), +(@NPC_RAGEPAW*100+2,9,1,0,0,0,100,0,100,100,0,0,11,52553,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Spellcast Empowered Tree of Life'), +(@NPC_RAGEPAW*100+2,9,2,0,0,0,100,0,0,0,0,0,2,113,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Set faction'), +(@NPC_RAGEPAW*100+2,9,3,0,0,0,100,0,0,0,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Remove unit_field_bytes1 (kneel)'), +(@NPC_RAGEPAW*100+2,9,4,0,0,0,100,0,2600,2600,0,0,1,2,0,0,0,0,0,7,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Say line'), +(@NPC_RAGEPAW*100+2,9,5,0,0,0,100,0,4700,4700,0,0,53,1,@NPC_RAGEPAW,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Start WP movement'), +(@NPC_RAGEPAW*100+2,9,6,0,0,0,100,0,0,0,0,0,22,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 2 - Set event phase 3'), + +(@NPC_RAGEPAW*100+3,9,0,0,0,0,100,0,0,0,0,0,101,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 3 - Set homeposition'), +(@NPC_RAGEPAW*100+3,9,1,0,0,0,100,0,6000,6000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Tur Ragepaw script 3 - Say line'), +(@NPC_RAGEPAW*100+3,9,2,0,0,0,100,0,300,300,0,0,12,@NPC_URSOC,6,60000,0,0,0,8,0,0,0,4893.267,-3842.415,337.6485,3.124139,'Tur Ragepaw script 3 - Summon Ursoc'), + +(@NPC_SPIRIT*100,9,0,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Spirit of Ursoc script 0 - Say line'), +(@NPC_SPIRIT*100,9,1,0,0,0,100,0,5000,5000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Spirit of Ursoc script 0 - Say line'); diff --git a/sql/updates/world/2013_04_11_01_world_misc.sql b/sql/updates/world/2013_04_11_01_world_misc.sql new file mode 100644 index 00000000000..699f65f1c5a --- /dev/null +++ b/sql/updates/world/2013_04_11_01_world_misc.sql @@ -0,0 +1,64 @@ +SET @NPC_LARRY := 19720; +SET @NPC_MALONE := 19725; +SET @NPC_JACK := 19726; + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8033; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(8033, 0, 0, 'Ezekiel said that you might have a certain book...', 1, 1, 0, 0, 0, 0, ''); + +UPDATE `creature_template` SET `AIName`='SmartAI', `ScriptName`='' WHERE `entry` IN (@NPC_LARRY,@NPC_MALONE,@NPC_JACK); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_LARRY,@NPC_MALONE,@NPC_JACK) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@NPC_LARRY,0,0,1,25,0,100,0,0,0,0,0,2,1194,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Dirty" Larry - On reset - Set faction'), +(@NPC_LARRY,0,1,2,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Dirty" Larry - On reset - Set unit_flags IMMUNE_TO_PC'), +(@NPC_LARRY,0,2,3,61,0,100,0,0,0,0,0,81,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Dirty" Larry - On reset - Set npcflag gossip, questgiver'), +(@NPC_LARRY,0,3,4,61,0,100,0,0,0,0,0,45,1,2,0,0,0,0,10,70376,@NPC_MALONE,0,0,0,0,0,'Dirty" Larry - On reset - Set data 1 2 "Epic" Malone'), +(@NPC_LARRY,0,4,0,61,0,100,0,0,0,0,0,45,1,2,0,0,0,0,10,70377,@NPC_JACK,0,0,0,0,0,'Dirty" Larry - On reset - Set data 1 2 "Creepjack"'), +(@NPC_LARRY,0,5,6,62,0,100,0,8033,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dirty" Larry - On gossip select - Store targetlist'), +(@NPC_LARRY,0,6,7,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dirty" Larry - On gossip select - Close Gossip'), +(@NPC_LARRY,0,7,8,61,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On gossip select - Say line'), +(@NPC_LARRY,0,8,9,61,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On gossip select - Set npcflag none'), +(@NPC_LARRY,0,9,10,61,0,100,0,0,0,0,0,70,0,0,0,0,0,0,10,70376,@NPC_MALONE,0,0,0,0,0,'Dirty" Larry - On gossip select - Respawn "Epic" Malone '), +(@NPC_LARRY,0,10,0,61,0,100,0,0,0,0,0,70,0,0,0,0,0,0,10,70377,@NPC_JACK,0,0,0,0,0,'Dirty" Larry - On gossip select - Respawn "Creepjack" '), +(@NPC_LARRY,0,11,0,52,0,100,0,0,@NPC_LARRY,0,0,1,1,5000,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Say line'), +(@NPC_LARRY,0,12,0,52,0,100,0,1,@NPC_LARRY,0,0,1,2,2000,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Say line'), +(@NPC_LARRY,0,13,0,52,0,100,0,2,@NPC_LARRY,0,0,1,3,2000,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Say line'), +(@NPC_LARRY,0,14,0,52,0,100,0,3,@NPC_LARRY,0,0,1,4,2000,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Say line'), +(@NPC_LARRY,0,15,16,52,0,100,0,4,@NPC_LARRY,0,0,2,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Set faction'), +(@NPC_LARRY,0,16,17,61,0,100,0,0,0,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On text over - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_LARRY,0,17,18,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,12,1,0,0,0,0,0,0,'Dirty" Larry - On text over - Attack'), +(@NPC_LARRY,0,18,19,61,0,100,0,0,0,0,0,100,1,0,0,0,0,0,10,70376,@NPC_MALONE,0,0,0,0,0,'Dirty" Larry - On text over - Send targetlist to "Epic" Malone'), +(@NPC_LARRY,0,19,20,61,0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,70376,@NPC_MALONE,0,0,0,0,0,'Dirty" Larry - On text over - Set data 1 1 "Epic" Malone'), +(@NPC_LARRY,0,20,21,61,0,100,0,0,0,0,0,100,1,0,0,0,0,0,10,70377,@NPC_JACK,0,0,0,0,0,'Dirty" Larry - On text over - Send targetlist to "Creepjack"'), +(@NPC_LARRY,0,21,0,61,0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,70377,@NPC_JACK,0,0,0,0,0,'Dirty" Larry - On text over - Set data 1 1 "Creepjack"'), +(@NPC_LARRY,0,22,23,2,0,100,0,0,20,0,0,15,10231,0,0,0,0,0,16,0,0,0,0,0,0,0,'Dirty" Larry - On health below 20% - Quest credit'), +(@NPC_LARRY,0,23,24,61,0,100,0,0,0,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On health below 20% - Say line'), +(@NPC_LARRY,0,24,3,61,0,100,0,0,0,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On health below 20% - Evade'), +(@NPC_LARRY,0,25,0,11,0,100,0,0,0,0,0,42,0,15,0,0,0,0,1,0,0,0,0,0,0,0,'Dirty" Larry - On spawn - Set invincibility HP level'), + +(@NPC_MALONE,0,0,1,25,0,100,0,0,0,0,0,2,1194,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Epic" Malone - On reset - Set faction'), +(@NPC_MALONE,0,1,0,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Epic" Malone - On reset - Set unit_flags IMMUNE_TO_PC'), +(@NPC_MALONE,0,2,3,38,0,100,0,1,1,0,0,2,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Epic" Malone - On data 1 1 set - Set faction'), +(@NPC_MALONE,0,3,4,61,0,100,0,0,0,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Epic" Malone - On data 1 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_MALONE,0,4,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,12,1,0,0,0,0,0,0,'"Epic" Malone - On data 1 1 set - Attack'), +(@NPC_MALONE,0,5,0,38,0,100,0,1,2,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Epic" Malone - On data 1 2 set - Evade'), + +(@NPC_JACK,0,0,1,25,0,100,0,0,0,0,0,2,1194,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Creepjack" - On reset - Set faction'), +(@NPC_JACK,0,1,0,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Creepjack" - On reset - Set unit_flags IMMUNE_TO_PC'), +(@NPC_JACK,0,2,3,38,0,100,0,1,1,0,0,2,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Creepjack" - On data 1 1 set - Set faction'), +(@NPC_JACK,0,3,4,61,0,100,0,0,0,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Creepjack" - On data 1 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_JACK,0,4,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,12,1,0,0,0,0,0,0,'"Creepjack" - On data 1 1 set - Attack'), +(@NPC_JACK,0,5,0,38,0,100,0,1,2,0,0,24,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'"Creepjack" - On data 1 2 set - Evade'); + +DELETE FROM `creature_text` WHERE `entry`=@NPC_LARRY; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@NPC_LARRY, 0, 0, 'Time to teach you a lesson in manners, little boy! ', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'), +(@NPC_LARRY, 1, 0, 'I''m now going to give you to the count of "3" to get out of here before I sick the dogs on you.', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'), +(@NPC_LARRY, 2, 0, '1...', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'), +(@NPC_LARRY, 3, 0, '2...', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'), +(@NPC_LARRY, 4, 0, 'Time to meet your maker!', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'), +(@NPC_LARRY, 5, 0, 'Alright, we give up! Don''t hurt us!', 12, 0, 100, 0, 0, 0, '"Dirty" Larry'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8033; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,8033,0,0,9,10231,0,0,0,'','"Dirty" Larry only show gossip if player is on and has not completed What Book? I Dont See Any Book'); diff --git a/sql/updates/world/2013_04_11_02_world_misc.sql b/sql/updates/world/2013_04_11_02_world_misc.sql new file mode 100644 index 00000000000..be9652a13bb --- /dev/null +++ b/sql/updates/world/2013_04_11_02_world_misc.sql @@ -0,0 +1,69 @@ +SET @NPC_HEBJIN := 28636; +SET @NPC_BAT := 28639; +SET @GO_DRUM := 190695; + +DELETE FROM `creature` WHERE `guid` IN (117079,117301); + +UPDATE `creature_template` SET `speed_run`=0.857143, `unit_flags`=33024, `AIName`='SmartAI' WHERE `entry`=@NPC_HEBJIN; +UPDATE `creature_template` SET `speed_run`=2, `unit_flags`=256, `AIName`='SmartAI', `InhabitType`=4 WHERE `entry`=@NPC_BAT; + +DELETE FROM `event_scripts` WHERE `id`=18773; +INSERT INTO `event_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`) VALUES +(18773,0,10,@NPC_HEBJIN,180000,0,5988.715,-3878.036,417.1502,2.356194); + +DELETE FROM `creature_text` WHERE `entry`=@NPC_HEBJIN; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_HEBJIN,0,0,'Who''s that beatin'' on my drum?',14,0,100,5,0,12009,'Heb''Jin'), +(@NPC_HEBJIN,1,0,'I''m gonna come down there and kill you good, $r!',14,0,100,15,0,0,'Heb''Jin'), +(@NPC_HEBJIN,2,0,'Now you gonna die!',14,0,100,0,0,0,'Heb''Jin'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=52151; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,52151,0,31,3,@NPC_BAT,0,0,'','Spell Bat Net targets Heb''Jin''s Bat'); + +DELETE FROM `waypoints` WHERE `entry`=@NPC_BAT; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@NPC_BAT,1,5982.633,-3879.573,422.4082,'Heb''Jin''s Bat'), +(@NPC_BAT,2,5968.549,-3869.597,420.1865,'Heb''Jin''s Bat'), +(@NPC_BAT,3,5954.345,-3851.714,395.2976,'Heb''Jin''s Bat'), +(@NPC_BAT,4,5934.977,-3822.782,369.5197,'Heb''Jin''s Bat'); + +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry`=@GO_DRUM; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_HEBJIN,@NPC_BAT) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@GO_DRUM AND `source_type`=1; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_HEBJIN*100,@NPC_BAT*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_HEBJIN,0,0,0,54,0,100,0,0,0,0,0,80,@NPC_HEBJIN*100,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin - Just summoned - Run script'), +(@NPC_HEBJIN,0,1,2,38,0,100,0,0,1,0,0,11,52354,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin - On data 0 1 set - Spellcast Script Effect - Creature Attack GUID from Dot Variable'), +(@NPC_HEBJIN,0,2,3,61,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,5937.22,-3820.871,366.5563,0, 'Heb''Jin - On data 0 1 set - Move to position'), +(@NPC_HEBJIN,0,3,4,61,0,100,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin - On data 0 1 set - Say line'), +(@NPC_HEBJIN,0,4,5,61,0,100,0,0,0,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin - On data 0 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_HEBJIN,0,5,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin - On data 0 1 set - Start attack'), +(@NPC_HEBJIN,0,6,0,0,0,100,0,1000,1000,7000,8000,11,12734,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin - On update IC - Spellcast Ground Smash'), +(@NPC_HEBJIN,0,7,0,0,0,100,0,5000,5000,10000,12000,11,15548,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin - On update IC - Spellcast Thunder Clap'), +(@NPC_HEBJIN,0,8,0,13,0,100,0,12000,15000,0,0,11,12555,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Heb''Jin - On target casting - Spellcast Pummel'), + +(@NPC_BAT,0,0,1,11,0,100,0,0,0,0,0,91,7,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spawn - Remove unit_field_bytes1 (dead)'), +(@NPC_BAT,0,1,2,61,0,100,0,0,0,0,0,11,52353,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spawn - Spellcast Script Effect - Creature Capture GUID to Dot Variable'), +(@NPC_BAT,0,2,0,61,0,100,0,0,0,0,0,4,10892,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spawn - Play sound'), +(@NPC_BAT,0,3,0,27,0,100,1,0,0,0,0,53,1,@NPC_BAT,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On passenger boarded - Start WP movement'), +(@NPC_BAT,0,4,5,40,0,100,0,4,@NPC_BAT,0,0,28,43671,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On WP 4 reached - Remove aura Ride Vehicle'), +(@NPC_BAT,0,5,6,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,19,@NPC_HEBJIN,10,0,0,0,0,0, 'Heb''Jin''s Bat - On WP 4 reached - Set data 0 1 Heb''Jin'), +(@NPC_BAT,0,6,0,61,0,100,0,0,0,0,0,80,@NPC_BAT*100,2,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On WP 4 reached - Run script'), +(@NPC_BAT,0,7,8,8,0,100,0,52151,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spellhit Bat Net - Set unit_flags IMMUNE_TO_PC'), +(@NPC_BAT,0,8,9,61,0,100,0,0,0,0,0,90,7,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spellhit Bat Net - Set unit_field_bytes1 (dead)'), +(@NPC_BAT,0,9,0,61,0,100,0,0,0,0,0,41,5000,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat - On spellhit Bat Net - Despawn after 5 seconds'), + +(@GO_DRUM,1,0,1,70,0,100,0,2,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Heb''Jin''s Drum - On state changed - Store targetlist'), +(@GO_DRUM,1,1,0,61,0,100,0,0,0,0,0,100,1,0,0,0,0,0,19,@NPC_HEBJIN,100,0,0,0,0,0, 'Heb''Jin''s Drum - On state changed - Send targetlist to Heb''Jin'), + +(@NPC_HEBJIN*100,9,0,0,0,0,100,0,0,0,0,0,11,52353,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin script - Spellcast Script Effect - Creature Capture GUID to Dot Variable'), +(@NPC_HEBJIN*100,9,1,0,0,0,100,0,3200,3200,0,0,11,52154,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin script - Spellcast Taunt'), +(@NPC_HEBJIN*100,9,2,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin script - Say line'), +(@NPC_HEBJIN*100,9,3,0,0,0,100,0,300,300,0,0,12,@NPC_BAT,8,0,0,0,0,8,0,0,0,5984.547,-3882.621,417.4379,1.919862, 'Heb''Jin script - Summon Heb''Jin''s Bat'), +(@NPC_HEBJIN*100,9,4,0,0,0,100,0,0,0,0,0,100,1,0,0,0,0,0,19,@NPC_BAT,10,0,0,0,0,0, 'Heb''Jin script - Send targetlist'), +(@NPC_HEBJIN*100,9,5,0,0,0,100,0,5700,5700,0,0,1,1,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin script - Say line'), +(@NPC_HEBJIN*100,9,6,0,0,0,100,0,2400,2400,0,0,11,43671,0,0,0,0,0,19,@NPC_BAT,10,0,0,0,0,0, 'Heb''Jin script - Spellcast Ride Vehicle'), + +(@NPC_BAT*100,9,0,0,0,0,100,0,2000,2000,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Heb''Jin''s Bat script 1 - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_BAT*100,9,1,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,12,1,0,0,0,0,0,0, 'Heb''Jin''s Bat script 1 - Start attack'); diff --git a/sql/updates/world/2013_04_11_03_world_misc.sql b/sql/updates/world/2013_04_11_03_world_misc.sql new file mode 100644 index 00000000000..5f1e89d631d --- /dev/null +++ b/sql/updates/world/2013_04_11_03_world_misc.sql @@ -0,0 +1,8 @@ +DELETE FROM `spell_target_position` WHERE `id`=52464; +INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES +(52464, 609, 2384.13, -5900.07, 107.998, 0); + +UPDATE `gameobject_template` SET `ScriptName`='' WHERE `entry`=190767; + +DELETE FROM `creature` WHERE `guid`=129164; +DELETE FROM `creature_addon` WHERE `guid`=129164; diff --git a/sql/updates/world/2013_04_12_00_world_smart_scripts.sql b/sql/updates/world/2013_04_12_00_world_smart_scripts.sql new file mode 100644 index 00000000000..6e7dddee60c --- /dev/null +++ b/sql/updates/world/2013_04_12_00_world_smart_scripts.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=37120; +DELETE FROM `smart_scripts` WHERE `entryorguid`=37120; +INSERT INTO `smart_scripts` (`entryorguid`,`event_type`,`event_param1`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUES +(37120,20,24549,57,49888,1,7,'Highlord Darion Mograine - On quest rewarded - Remove item from player'); diff --git a/sql/updates/world/2013_04_13_00_world_misc.sql b/sql/updates/world/2013_04_13_00_world_misc.sql new file mode 100644 index 00000000000..b2c6d11d9d9 --- /dev/null +++ b/sql/updates/world/2013_04_13_00_world_misc.sql @@ -0,0 +1,4 @@ +-- Malcrom +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=2305 AND `source_type`=0 AND `id`=2; +-- Kirkhammett +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=15656 AND `source_type`=0 AND `id`=0 AND `link`=1; diff --git a/sql/updates/world/2013_04_13_01_world_misc.sql b/sql/updates/world/2013_04_13_01_world_misc.sql new file mode 100644 index 00000000000..8b8afe05026 --- /dev/null +++ b/sql/updates/world/2013_04_13_01_world_misc.sql @@ -0,0 +1,22 @@ +-- Runtime errors +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=1124 AND `source_type`=0 AND `id`=14 AND `link`=15; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=1124 AND `source_type`=0 AND `id`=15 AND `link`=16; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=5710 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=5997 AND `source_type`=0 AND `id`=8 AND `link`=9; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=7843 AND `source_type`=0 AND `id`=9 AND `link`=10; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=8564 AND `source_type`=0 AND `id`=12 AND `link`=13; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=10824 AND `source_type`=0 AND `id`=8 AND `link`=9; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12236 AND `source_type`=0 AND `id`=3 AND `link`=4; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12236 AND `source_type`=0 AND `id`=4 AND `link`=5; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12236 AND `source_type`=0 AND `id`=9 AND `link`=10; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12322 AND `source_type`=0 AND `id`=8 AND `link`=9; +-- Timed action scripts aren't supposed to have links set on them +UPDATE `smart_scripts` SET `link`=0, `event_type`=0 WHERE `entryorguid`=83600 AND `source_type`=9 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0, `event_type`=0 WHERE `entryorguid`=83600 AND `source_type`=9 AND `id`=2 AND `link`=3; +UPDATE `smart_scripts` SET `event_type`=0 WHERE `entryorguid`=83600 AND `source_type`=9 AND `id`=3 AND `link`=0; +-- Aforementioned issue about links on timed scripts +UPDATE `smart_scripts` SET `link`=0, `event_type`=0 WHERE `entryorguid`=305400 AND `source_type`=9 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `event_type`=0 WHERE `entryorguid`=305400 AND `source_type`=9 AND `id`=2 AND `link`=0; +-- Missing AI's +UPDATE `creature_template` SET `ScriptName`='SmartAI' WHERE `entry` IN +(10876,14389,13326,13328,12050,12053,10981,10986,10990,11678,11839,12051,12127,13179,13284,13438,13442,13443,13447,13577,13798,14282,14283,10987,10982,11603,11605,13089,13097,13089); diff --git a/sql/updates/world/2013_04_13_02_world_smart_scripts.sql b/sql/updates/world/2013_04_13_02_world_smart_scripts.sql new file mode 100644 index 00000000000..78ef1e82a00 --- /dev/null +++ b/sql/updates/world/2013_04_13_02_world_smart_scripts.sql @@ -0,0 +1,7 @@ +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=19354; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=19354; +DELETE FROM `smart_scripts` WHERE `entryorguid`=19354 AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`id`,`event_type`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUES +(19354,0,0,0,8000,12000,8000,14000,11,16856,0,2,'Arzeth the Merciless - Cast Mortal Strike'), +(19354,1,9,0,0,30,12000,14000,11,15245,1,2,'Arzeth the Merciless - Cast Shadow Bolt Volley'), +(19354,2,8,1,35460,0,0,0,36,20680,1,1,'Arzeth the Merciless - Change Template to Arzeth the Powerless after using Staff of the Dreghood Elders'); diff --git a/sql/updates/world/2013_04_13_03_world_smart_scripts.sql b/sql/updates/world/2013_04_13_03_world_smart_scripts.sql new file mode 100644 index 00000000000..15302e15008 --- /dev/null +++ b/sql/updates/world/2013_04_13_03_world_smart_scripts.sql @@ -0,0 +1,5 @@ +UPDATE `smart_scripts` SET `event_type`=37 WHERE `entryorguid` IN (589,476,95) AND `id`=0 AND `source_type`=0; + +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=3448 AND `source_type`=0 AND `id`=3; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=61 AND `source_type`=1 AND `id`=3; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=22231 AND `source_type`=0 AND `id`=0; diff --git a/sql/updates/world/2013_04_14_00_world_game_event.sql b/sql/updates/world/2013_04_14_00_world_game_event.sql new file mode 100644 index 00000000000..82929053e8c --- /dev/null +++ b/sql/updates/world/2013_04_14_00_world_game_event.sql @@ -0,0 +1,2 @@ +ALTER TABLE `game_event` +ADD COLUMN `announce` tinyint(3) unsigned NULL DEFAULT 2 COMMENT '0 dont announce, 1 announce, 2 value from config' AFTER `world_event`; diff --git a/sql/updates/world/2013_04_14_00_world_misc.sql b/sql/updates/world/2013_04_14_00_world_misc.sql new file mode 100644 index 00000000000..1f239cf0d1f --- /dev/null +++ b/sql/updates/world/2013_04_14_00_world_misc.sql @@ -0,0 +1,146 @@ +SET @CGUID := 110258; + +SET @NPC_BUNNY := 23837; +SET @NPC_WARRIOR := 28388; +SET @NPC_KUTUBESA := 28494; +SET @NPC_GAWANIL := 28495; +SET @NPC_CHULO := 28496; +SET @NPC_MEDICINEMAN := 28504; + +UPDATE `creature` SET `spawntimesecs`=600 WHERE `id`=@NPC_KUTUBESA; +DELETE FROM `creature` WHERE `guid` IN (117763,117764,117766); +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+00 AND @CGUID+25; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(@CGUID+00, @NPC_MEDICINEMAN, 571, 1, 1, 5591.043, -3475.191, 351.5252, 0.1047198, 300, 0, 0), +(@CGUID+01, @NPC_MEDICINEMAN, 571, 1, 1, 5566.45, -3498.799, 351.0538, 4.590216, 300, 0, 0), +(@CGUID+02, @NPC_MEDICINEMAN, 571, 1, 1, 5547.046, -3498.974, 350.4519, 2.339428, 300, 0, 2), +(@CGUID+03, @NPC_MEDICINEMAN, 571, 1, 1, 5526.021, -3355.056, 364.3894, 4.677482, 300, 0, 0), +(@CGUID+04, @NPC_MEDICINEMAN, 571, 1, 1, 5517.316, -3449.934, 351.4341, 3.054326, 300, 0, 0), +(@CGUID+05, @NPC_BUNNY, 571, 1, 1, 5493.355, -3456.877, 350.4105, 2.024582, 300, 0, 0), +(@CGUID+06, @NPC_MEDICINEMAN, 571, 1, 1, 5521.364, -3386.496, 350.327, 5.654867, 300, 0, 2), +(@CGUID+07, @NPC_MEDICINEMAN, 571, 1, 1, 5492.875, -3459.563, 350.4502, 1.58825, 300, 0, 0), +(@CGUID+08, @NPC_MEDICINEMAN, 571, 1, 1, 5529.104, -3382.233, 350.4102, 2.356194, 300, 0, 0), +(@CGUID+09, @NPC_MEDICINEMAN, 571, 1, 1, 5541.636, -3425.828, 350.7735, 1.58825, 300, 0, 0), +(@CGUID+10, @NPC_WARRIOR, 571, 1, 1, 5674.67, -3491.495, 364.4726, 0.5366452, 300, 0, 0), +(@CGUID+11, @NPC_WARRIOR, 571, 1, 1, 5648.147, -3448.292, 362.8895, 5.986479, 300, 0, 0), +(@CGUID+12, @NPC_WARRIOR, 571, 1, 1, 5666.273, -3428.566, 365.5977, 6.085189, 300, 0, 0), +(@CGUID+13, @NPC_WARRIOR, 571, 1, 1, 5503.863, -3369.427, 363.1629, 4.918784, 300, 0, 0), +(@CGUID+14, @NPC_WARRIOR, 571, 1, 1, 5533.224, -3322.825, 366.5383, 0.8552113, 300, 0, 0), +(@CGUID+15, @NPC_WARRIOR, 571, 1, 1, 5528.603, -3501.259, 350.6893, 0.7853982, 300, 0, 0), +(@CGUID+16, @NPC_WARRIOR, 571, 1, 1, 5646.593, -3513.597, 362.6178, 0.2094395, 300, 0, 0), +(@CGUID+17, @NPC_WARRIOR, 571, 1, 1, 5525.68, -3477.987, 350.4114, 5.487214, 300, 0, 0), +(@CGUID+18, @NPC_BUNNY, 571, 1, 1, 5527.289, -3380.66, 350.4102, 1.867502, 120, 0, 0), +(@CGUID+19, @NPC_GAWANIL, 571, 1, 1, 5601.297, -3501.478, 350.4102, 2.059489, 600, 0, 0), +(@CGUID+20, @NPC_CHULO, 571, 1, 1, 5508.03, -3418.04, 350.9052, 5.689773, 600, 0, 0), +(@CGUID+21, @NPC_BUNNY, 571, 1, 1, 5627.774, -3505.409, 355.8583, 5.044002, 120, 0, 0), +(@CGUID+22, @NPC_BUNNY, 571, 1, 1, 5637.709, -3478.724, 354.5638, 4.502949, 120, 0, 0), +(@CGUID+23, @NPC_BUNNY, 571, 1, 1, 5553.081, -3459.962, 350.4102, 6.213372, 120, 0, 0), +(@CGUID+24, @NPC_BUNNY, 571, 1, 1, 5618.041, -3450.443, 353.8071, 4.939282, 120, 0, 0), +(@CGUID+25, @NPC_BUNNY, 571, 1, 1, 5647.352, -3502.605, 362.8272, 4.39823, 120, 0, 0); + +DELETE FROM `creature_addon` WHERE `guid` IN (@CGUID+02,@CGUID+06,@CGUID+19,@CGUID+20); +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`emote`) VALUES +(@CGUID+02,(@CGUID+02)*10,1,0), +(@CGUID+06,(@CGUID+06)*10,1,0), +(@CGUID+19,0,1,375), +(@CGUID+20,0,1,375); + +DELETE FROM `waypoint_data` WHERE `id` IN ((@CGUID+02)*10,(@CGUID+06)*10); +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +((@CGUID+02)*10,1,5495.677,-3457.071,350.3303,0,10000,0,(@CGUID+02)*100+1,100,0), +((@CGUID+02)*10,2,5579.755,-3533.386,350.4519,0,10000,0,(@CGUID+02)*100+2,100,0), +((@CGUID+06)*10,1,5525.278,-3382.127,350.3272,0,10000,0,(@CGUID+06)*100+1,100,0), +((@CGUID+06)*10,2,5521.364,-3386.496,350.327,0,0,0,0,100,0), +((@CGUID+06)*10,3,5611.445,-3474.975,350.4102,0,10000,0,(@CGUID+06)*100+2,100,0), +((@CGUID+06)*10,4,5521.364,-3386.496,350.327,0,0,0,0,100,0); + +DELETE FROM `waypoint_scripts` WHERE `id` IN ((@CGUID+02)*100+1,(@CGUID+02)*100+2,(@CGUID+06)*100+1,(@CGUID+06)*100+2); +INSERT INTO `waypoint_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`,`guid`) VALUES +((@CGUID+02)*100+1,0,30,0,0,0,0,0,0,3.001966,858), +((@CGUID+02)*100+1,1,15,51733,1,0,0,0,0,0,859), +((@CGUID+02)*100+2,1,15,51733,1,0,0,0,0,0,860), +((@CGUID+06)*100+1,1,15,51733,1,0,0,0,0,0,861), +((@CGUID+06)*100+2,1,15,51733,1,0,0,0,0,0,862); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=51511; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN (@NPC_KUTUBESA,@NPC_GAWANIL,@NPC_CHULO); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,3,51511,0,31,0,3,@NPC_BUNNY,0,0,'','Spell Toss Ice Boulder targets ELM General Purpose Bunny'), +(13,3,51511,1,31,0,3,@NPC_WARRIOR,0,0,'','Spell Toss Ice Boulder targets Jin''Alai Warrior'), +(13,3,51511,2,31,0,3,@NPC_MEDICINEMAN,0,0,'','Spell Toss Ice Boulder targets Jin''Alai Medicine Man'), +(22,1,@NPC_KUTUBESA,0,38,1,100,0,0,0,'','SAI Kutub''sa triggers only when at full health'), +(22,1,@NPC_GAWANIL,0,38,1,100,0,0,0,'','SAI Gawanil triggers only when at full health'), +(22,1,@NPC_CHULO,0,38,1,100,0,0,0,'','SAI Chulo the Mad triggers only when at full health'); + +DELETE FROM `creature_template_addon` WHERE `entry`=@NPC_WARRIOR; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`emote`) VALUES +(@NPC_WARRIOR,1,375); + +DELETE FROM `creature_text` WHERE `entry` IN (@NPC_KUTUBESA,@NPC_GAWANIL,@NPC_CHULO); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_KUTUBESA,0,0,'Death to the Zandalari and their puppets! Nothing can stop us now!',14,0,100,15,0,0,'Kutube''sa'), +(@NPC_GAWANIL,0,0,'Kill them! Kill them all and take back Zim''Torga!',14,0,100,15,0,0,'Gawanil'), +(@NPC_CHULO,0,0,'Hah! You''ll not get my treasure!',14,0,100,15,0,0,'Chulo the Mad'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (28387,@NPC_WARRIOR,@NPC_KUTUBESA,@NPC_GAWANIL,@NPC_CHULO,@NPC_MEDICINEMAN); +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry` IN (190618,190619,190620,190630); +DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (28387,@NPC_WARRIOR,@NPC_KUTUBESA,@NPC_GAWANIL,@NPC_CHULO,@NPC_MEDICINEMAN); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-98550,-98551,-(@CGUID+05),-(@CGUID+18),28387,@NPC_WARRIOR,@NPC_KUTUBESA,@NPC_GAWANIL,@NPC_CHULO,@NPC_MEDICINEMAN) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (190618,190619,190620,190630) AND `source_type`=1; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-98550,0,0,0,38,0,100,0,0,1,0,0,11,51848,0,0,0,0,0,1,0,0,0,0,0,0,0,'ELM General Purpose Bunny - On event triggered - Spellcast Cauldron Disturbed'), +(-98551,0,0,0,38,0,100,0,0,1,0,0,11,51848,0,0,0,0,0,1,0,0,0,0,0,0,0,'ELM General Purpose Bunny - On event triggered - Spellcast Cauldron Disturbed'), +(-(@CGUID+05),0,0,0,38,0,100,0,0,1,0,0,11,51848,0,0,0,0,0,1,0,0,0,0,0,0,0,'ELM General Purpose Bunny - On event triggered - Spellcast Cauldron Disturbed'), +(-(@CGUID+18),0,0,0,38,0,100,0,0,1,0,0,11,51848,0,0,0,0,0,1,0,0,0,0,0,0,0,'ELM General Purpose Bunny - On event triggered - Spellcast Cauldron Disturbed'), + +(28387,0,0,0,0,0,100,0,5000,7000,10000,14000,11,54673,0,0,0,0,0,2,0,0,0,0,0,0,0,'Zim''Torga Defender - On update IC - Spellcast Ice Boulder'), +(28387,0,1,0,1,0,100,0,20000,30000,30000,30000,11,51511,0,0,0,0,0,1,0,0,0,0,0,0,0,'Zim''Torga Defender - On update OOC - Spellcast Toss Ice Boulder'), + +(@NPC_WARRIOR,0,0,0,4,0,100,0,0,0,0,0,11,38556,0,0,0,0,0,2,0,0,0,0,0,0,0,'Jin''Alai Warrior - On aggro - Spellcast Throw'), +(@NPC_WARRIOR,0,1,0,0,0,100,0,5000,6000,10000,12000,11,54630,0,0,0,0,0,2,0,0,0,0,0,0,0,'Jin''Alai Warrior - On update IC - Spellcast Poison Tipped Spear'), +(@NPC_WARRIOR,0,2,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,@CGUID+20,@NPC_CHULO,0,0,0,0,0,'Jin''Alai Warrior - On death (10% chance) - Set data 0 1 Chulo the Mad'), +(@NPC_WARRIOR,0,3,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,103225,@NPC_KUTUBESA,0,0,0,0,0,'Jin''Alai Warrior - On death (10% chance) - Set data 0 1 Kutube''sa'), +(@NPC_WARRIOR,0,4,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,@CGUID+19,@NPC_GAWANIL,0,0,0,0,0,'Jin''Alai Warrior - On death (10% chance) - Set data 0 1 Gawanil'), + +(@NPC_KUTUBESA,0,0,1,38,0,100,0,0,1,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On data 0 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_KUTUBESA,0,1,2,61,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On data 0 1 set - Set visible'), +(@NPC_KUTUBESA,0,2,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On data 0 1 set - Say line'), +(@NPC_KUTUBESA,0,3,0,4,0,100,0,0,0,0,0,11,57793,0,0,0,0,0,2,0,0,0,0,0,0,0,'Kutube''sa - On aggro - Spellcast Heroic Leap'), +(@NPC_KUTUBESA,0,4,0,0,0,100,0,3000,5000,17500,20000,11,35144,0,0,0,0,0,2,0,0,0,0,0,0,0,'Kutube''sa - On update IC - Spellcast Vicious Rend'), +(@NPC_KUTUBESA,0,5,0,0,0,100,0,6000,8000,20000,25000,11,49807,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On update IC - Spellcast Whirlwind'), +(@NPC_KUTUBESA,0,6,0,6,0,100,0,0,0,0,0,11,51815,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On death - The Leaders at Jin''Alai: Summon the Treasure of Kutube''sa'), +(@NPC_KUTUBESA,0,7,8,11,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On spawn - Set invisible'), +(@NPC_KUTUBESA,0,8,0,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Kutube''sa - On spawn - Set unit_flags IMMUNE_TO_PC'), + +(@NPC_GAWANIL,0,0,1,38,0,100,0,0,1,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On data 0 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_GAWANIL,0,1,2,61,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On data 0 1 set - Set visible'), +(@NPC_GAWANIL,0,2,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On data 0 1 set - Say line'), +(@NPC_GAWANIL,0,3,0,9,0,100,0,0,40,3400,4800,11,20791,0,0,0,0,0,2,0,0,0,0,0,0,0,'Gawanil - On target within 40y - Spellcast Shadow Bolt'), +(@NPC_GAWANIL,0,4,0,9,0,100,0,0,30,16500,18000,11,14868,0,0,0,0,0,2,0,0,0,0,0,0,0,'Gawanil - On target within 30y - Spellcast Curse of Agony'), +(@NPC_GAWANIL,0,5,0,9,0,100,0,0,30,16500,18000,11,39212,0,0,0,0,0,2,0,0,0,0,0,0,0,'Gawanil - On target within 30y - Spellcast Corruption'), +(@NPC_GAWANIL,0,6,0,2,0,100,0,0,70,20000,25000,11,35195,0,0,0,0,0,2,0,0,0,0,0,0,0,'Gawanil - On health below 70% - Spellcast Siphon Life'), +(@NPC_GAWANIL,0,7,0,6,0,100,0,0,0,0,0,11,51814,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On death - Spellcast The Leaders at Jin''Alai: Summon the Treasure of Gawanil'), +(@NPC_GAWANIL,0,8,9,11,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On spawn - Set invisible'), +(@NPC_GAWANIL,0,9,0,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Gawanil - On spawn - Set unit_flags IMMUNE_TO_PC'), + +(@NPC_CHULO,0,0,1,38,0,100,0,0,1,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On data 0 1 set - Remove unit_flags IMMUNE_TO_PC'), +(@NPC_CHULO,0,1,2,61,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On data 0 1 set - Set visible'), +(@NPC_CHULO,0,2,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On data 0 1 set - Say line'), +(@NPC_CHULO,0,3,0,0,0,100,0,3000,5000,17500,20000,11,17687,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On update IC - Spellcast Flurry'), +(@NPC_CHULO,0,4,0,0,0,100,0,6000,8000,20000,25000,11,50188,0,0,0,0,0,2,0,0,0,0,0,0,0,'Chulo the Mad - On update IC - Spellcast Wildly Flailing'), +(@NPC_CHULO,0,5,0,6,0,100,0,0,0,0,0,11,51813,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On death - The Leaders at Jin''Alai: Summon the Treasure of Chulo the Mad'), +(@NPC_CHULO,0,6,7,11,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On spawn - Set invisible'), +(@NPC_CHULO,0,7,0,61,0,100,0,0,0,0,0,18,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Chulo the Mad - On spawn - Set unit_flags IMMUNE_TO_PC'), + +(@NPC_MEDICINEMAN,0,0,0,11,0,100,0,0,0,0,0,11,51733,0,0,0,0,0,1,0,0,0,0,0,0,0,'Jin''Alai Medicine Man - On spawn - Spellcast Shadow Channelling'), +(@NPC_MEDICINEMAN,0,1,0,21,0,100,0,0,0,0,0,11,51733,0,0,0,0,0,1,0,0,0,0,0,0,0,'Jin''Alai Medicine Man - On homeposition - Spellcast Shadow Channelling'), +(@NPC_MEDICINEMAN,0,2,0,0,0,100,0,5000,6000,15000,20000,11,54626,0,0,0,0,0,2,0,0,0,0,0,0,0,'Jin''Alai Medicine Man - On update IC - Spellcast Vial of Poison'), +(@NPC_MEDICINEMAN,0,3,0,2,0,100,1,0,50,0,0,11,54633,0,0,0,0,0,1,0,0,0,0,0,0,0,'Jin''Alai Medicine Man - On health below 50% - Spellcast Drink Healing Potion'), +(@NPC_MEDICINEMAN,0,4,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,@CGUID+20,@NPC_CHULO,0,0,0,0,0,'Jin''Alai Medicine Man - On death (10% chance) - Set data 0 1 Chulo the Mad'), +(@NPC_MEDICINEMAN,0,5,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,103225,@NPC_KUTUBESA,0,0,0,0,0,'Jin''Alai Medicine Man - On death (10% chance) - Set data 0 1 Kutube''sa'), +(@NPC_MEDICINEMAN,0,6,0,6,0,10,0,0,0,0,0,45,0,1,0,0,0,0,10,@CGUID+19,@NPC_GAWANIL,0,0,0,0,0,'Jin''Alai Medicine Man - On death (10% chance) - Set data 0 1 Gawanil'), + +(190618,1,0,0,70,0,100,0,2,0,0,0,45,0,1,0,0,0,0,19,@NPC_BUNNY,5,0,0,0,0,0,'Blue Cauldron - On state changed - Set data 0 1 ELM General Purpose Bunny'), +(190619,1,0,0,70,0,100,0,2,0,0,0,45,0,1,0,0,0,0,19,@NPC_BUNNY,5,0,0,0,0,0,'Purple Cauldron - On state changed - Set data 0 1 ELM General Purpose Bunny'), +(190620,1,0,0,70,0,100,0,2,0,0,0,45,0,1,0,0,0,0,19,@NPC_BUNNY,5,0,0,0,0,0,'Red Cauldron - On state changed - Set data 0 1 ELM General Purpose Bunny'), +(190630,1,0,0,70,0,100,0,2,0,0,0,45,0,1,0,0,0,0,19,@NPC_BUNNY,5,0,0,0,0,0,'Green Cauldron - On state changed - Set data 0 1 ELM General Purpose Bunny'); diff --git a/sql/updates/world/2013_04_16_00_world_sai.sql b/sql/updates/world/2013_04_16_00_world_sai.sql new file mode 100644 index 00000000000..c45fd63a256 --- /dev/null +++ b/sql/updates/world/2013_04_16_00_world_sai.sql @@ -0,0 +1,54 @@ +SET @NPC_BUNNY1 := 23921; +SET @NPC_BUNNY2 := 23922; +SET @NPC_BUNNY3 := 23923; +SET @NPC_BUNNY4 := 23924; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=42564; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,42564,0,31,3,@NPC_BUNNY1,0,0,'','Spell Ever-burning Torch targets Halgrind Torch Bunny 01'), +(13,1,42564,1,31,3,@NPC_BUNNY2,0,0,'','Spell Ever-burning Torch targets Halgrind Torch Bunny 02'), +(13,1,42564,2,31,3,@NPC_BUNNY3,0,0,'','Spell Ever-burning Torch targets Halgrind Torch Bunny 03'), +(13,1,42564,3,31,3,@NPC_BUNNY4,0,0,'','Spell Ever-burning Torch targets Halgrind Torch Bunny 04'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (@NPC_BUNNY1,@NPC_BUNNY2,@NPC_BUNNY3,@NPC_BUNNY4); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_BUNNY1,@NPC_BUNNY2,@NPC_BUNNY3,@NPC_BUNNY4) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_BUNNY1,0,0,1,8,0,100,0,42564,0,0,0,11,42632,0,0,0,0,0,7,0,0,0,0,0,0,0,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Spellcast Mission: Eternal Flame: Bunny 01 Kill Credit'), +(@NPC_BUNNY1,0,1,2,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,868.8023,-4339.792,182.2122,1.937312,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY1,0,2,3,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,870.0853,-4333.663,175.9133,2.059488,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY1,0,3,4,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,863.741,-4335.814,175.8825,2.809975,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY1,0,4,5,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,865.0932,-4329.501,184.862,-1.239183,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY1,0,5,6,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,868.7471,-4339.819,182.2086,-2.216565,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY1,0,6,7,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,870.0593,-4333.669,175.9119,-3.019413,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY1,0,7,8,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,863.8395,-4335.782,175.8698,2.251473,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY1,0,8,0,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,865.0274,-4329.538,184.8592,-2.513274,'Halgrind Torch Bunny 01 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), + +(@NPC_BUNNY2,0,0,1,8,0,100,0,42564,0,0,0,11,42633,0,0,0,0,0,7,0,0,0,0,0,0,0,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Spellcast Mission: Eternal Flame: Bunny 02 Kill Credit'), +(@NPC_BUNNY2,0,1,2,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,990.3699,-4312.481,169.8106,-0.1396245,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY2,0,2,3,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,986.9997,-4317.327,175.7941,-0.9948372,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY2,0,3,4,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,984.7455,-4311.373,170.311,0.9250239,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY2,0,4,5,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,989.3688,-4306.89,178.847,-0.6806787,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY2,0,5,6,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,986.9559,-4317.405,175.7507,-0.7853968,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY2,0,6,7,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,990.3775,-4312.451,169.8137,-1.605702,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY2,0,7,8,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,984.8902,-4311.392,170.2798,-1.169369,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY2,0,8,0,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,989.3943,-4306.688,178.8235,1.448622,'Halgrind Torch Bunny 02 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), + +(@NPC_BUNNY3,0,0,1,8,0,100,0,42564,0,0,0,11,42634,0,0,0,0,0,7,0,0,0,0,0,0,0,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Spellcast Mission: Eternal Flame: Bunny 03 Kill Credit'), +(@NPC_BUNNY3,0,1,2,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,1082.445,-4486.045,197.2445,2.268925,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY3,0,2,3,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,1084.6,-4491.493,190.9798,1.239183,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY3,0,3,4,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,1088.523,-4486.683,191.1761,2.652894,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY3,0,4,5,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,1091.084,-4492.35,199.8263,1.53589,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY3,0,5,6,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,1082.465,-4486.012,197.2427,-2.530723,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY3,0,6,7,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,1084.627,-4491.507,190.978,2.583081,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY3,0,7,8,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,1088.549,-4486.602,191.1885,-0.4886912,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY3,0,8,0,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,1090.992,-4492.313,199.8432,-1.937316,'Halgrind Torch Bunny 03 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), + +(@NPC_BUNNY4,0,0,1,8,0,100,0,42564,0,0,0,11,42635,0,0,0,0,0,7,0,0,0,0,0,0,0,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Spellcast Mission: Eternal Flame: Bunny 04 Kill Credit'), +(@NPC_BUNNY4,0,1,2,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,800.0019,-4499.426,192.1779,0.5934101,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY4,0,2,3,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,793.686,-4502.086,187.2915,1.53589,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY4,0,3,4,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,798.1101,-4505.706,186.7136,-0.4886912,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY4,0,4,5,61,0,100,0,0,0,0,0,50,186457,20,0,0,0,0,8,0,0,0,794.305,-4506.923,196.7457,0.7330382,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Blacksmith Smoke (x2.0)'), +(@NPC_BUNNY4,0,5,6,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,800.0145,-4499.367,192.1402,-1.047198,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY4,0,6,7,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,793.655,-4502.067,187.294,2.268925,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY4,0,7,8,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,798.0519,-4505.68,186.7271,0.2094394,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'), +(@NPC_BUNNY4,0,8,0,61,0,100,0,0,0,0,0,50,186459,20,0,0,0,0,8,0,0,0,794.0874,-4507.057,196.7687,-0.2268925,'Halgrind Torch Bunny 04 - On spellhit Ever-burning Torch - Summon Stratholme Fire Medium'); diff --git a/sql/updates/world/2013_04_16_01_world_smart_scripts.sql b/sql/updates/world/2013_04_16_01_world_smart_scripts.sql new file mode 100644 index 00000000000..02af2caf3b3 --- /dev/null +++ b/sql/updates/world/2013_04_16_01_world_smart_scripts.sql @@ -0,0 +1 @@ +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=2369 AND `source_type`=0 AND `id`=7 AND `link`=8; diff --git a/sql/updates/world/2013_04_16_02_world_creature_text.sql b/sql/updates/world/2013_04_16_02_world_creature_text.sql new file mode 100644 index 00000000000..034c632d12a --- /dev/null +++ b/sql/updates/world/2013_04_16_02_world_creature_text.sql @@ -0,0 +1,44 @@ +UPDATE `creature_text` SET `entry`=29227 WHERE `entry`=29173 AND `groupid`=76; +UPDATE `creature_text` SET `entry`=36794 WHERE `entry`=36658 AND `groupid` IN (1,2); + +DELETE FROM `creature_text` WHERE `entry` IN (18879,17491); +INSERT INTO `creature_text`(`entry`,`groupid`,`id`,`text`,`type`,`comment`) VALUES +(18879,0,0,'The %s is very weak',16,'Phase Hunter - Emote'), +(17491,0,0,'Gakarah ma!',12,'Laughing Skull Rogue'), +(17491,0,1,'We are the true Horde!',12,'Laughing Skull Rogue'); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=26670; +INSERT INTO `smart_scripts` VALUES +(26670,0,0,1,1,0,100,6,0,0,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - Out Of Combat - Allow Combat Movement'), +(26670,0,1,0,61,0,100,0,0,0,0,0,20,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - Out Of Combat - Start Auto Attack'), +(26670,0,2,3,4,0,100,3,0,0,0,0,11,48854,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - On Aggro - Cast Shoot'), +(26670,0,3,0,61,0,100,0,0,0,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - On Aggro - Increment Phase'), +(26670,0,4,5,9,1,100,2,5,30,5000,8000,11,48854,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - At 5 - 30 Range - Cast Shoot'), +(26670,0,5,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - At 5 - 30 Range - Display ranged weapon'), +(26670,0,6,7,4,0,100,5,0,0,0,0,11,59241,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - On Aggro - Cast Shoot'), +(26670,0,7,0,61,0,100,0,0,0,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - On Aggro - Increment Phase'), +(26670,0,8,9,9,1,100,4,5,30,5000,8000,11,59241,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - At 5 - 30 Range - Cast Shoot'), +(26670,0,9,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - At 5 - 30 Range - Display ranged weapon'), +(26670,0,10,11,9,1,100,6,25,80,0,0,21,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 25 - 80 Range - Allow Combat Movement'), +(26670,0,11,0,61,0,100,0,0,0,0,0,20,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 25 - 80 Range - Start Auto Attack'), +(26670,0,12,13,9,1,100,6,0,5,0,0,21,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 0 - 5 Range - Allow Combat Movement'), +(26670,0,13,14,61,0,100,0,0,0,0,0,40,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 0 - 5 Range - Display melee weapon'), +(26670,0,14,0,61,0,100,0,0,0,0,0,20,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 0 - 5 Range - Start Auto Attack'), +(26670,0,15,16,9,1,100,6,5,15,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 5 - 15 Range - Allow Combat Movement'), +(26670,0,16,0,61,0,100,0,0,0,0,0,20,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 5 - 15 Range - Start Auto Attack'),(26670,0,17,17,0,0,100,2,9000,14000,22000,26000,11,48871,0,0,0,0,0,5,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - In Combat - Cast Aimed Shot'),(26670,0,18,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - In Combat - Display ranged weapon'),(26670,0,19,20,0,0,100,4,9000,14000,22000,26000,11,59243,0,0,0,0,0,5,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - In Combat - Cast Aimed Shot'),(26670,0,20,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - In Combat - Display ranged weapon'),(26670,0,21,22,0,0,100,2,14000,17000,24000,27000,11,48872,1,0,0,0,0,6,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - In Combat - Cast Multi-Shot'),(26670,0,22,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Normal) - In Combat - Display ranged weapon'),(26670,0,23,24,0,0,100,4,14000,17000,24000,27000,11,59244,1,0,0,0,0,6,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - In Combat - Cast Multi-Shot'),(26670,0,24,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter (Heroic) - In Combat - Display ranged weapon'),(26670,0,25,0,2,0,100,7,0,15,0,0,23,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 15% HP - Increment Phase'),(26670,0,26,27,2,2,100,7,0,15,0,0,21,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 15% HP - Allow Combat Movement'),(26670,0,27,0,61,0,100,0,0,0,0,0,25,1,0,0,0,0,0,0,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - At 15% HP - Flee For Assist'),(26670,0,28,0,7,0,100,6,0,0,0,0,40,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ymirjar Flesh Hunter - On Evade - Display melee weapon'); + +DELETE FROM `creature_text` WHERE `entry` IN (23980,23954); +INSERT INTO `creature_text`(`entry`,`groupid`,`text`,`type`,`sound`,`comment`) VALUES +(23954,0,'I\'ll paint my face with your blood!',14,13207,'ingvar SAY_AGGRO_FIRST'), +(23954,1,'Mjul orm agn gjor!',14,13212,'ingvar SAY_KILL_FIRST'), +(23954,2,'My life for the... death god!',14,13213,'ingvar SAY_DEATH_FIRST'), +(23980,0,'I return! A second chance to carve out your skull!',14,13209,'ingvar SAY_AGGRO_SECOND'), +(23980,1,'I am a warrior born!',14,13214,'ingvar SAY_KILL_SECOND'), +(23980,2,'No! I can do... better! I can...',14,13211,'ingvar SAY_DEATH_SECOND'); + +DELETE FROM `creature_text` WHERE `entry`=11440; +INSERT INTO `creature_text`(`entry`,`id`,`text`,`type`,`probability`,`comment`) VALUES +(11440,0,'I\'ll crush you!',12,100,'Gordok Enforcer Aggro'), +(11440,1,'Me not feel so good.',12,100,'Gordok Enforcer Aggro'), +(11440,2,'Me smash! You die!',12,100,'Gordok Enforcer Aggro'), +(11440,3,'Raaar!!! Me smash $R!',12,100,'Gordok Enforcer Aggro'); diff --git a/sql/updates/world/2013_04_19_00_world_sai.sql b/sql/updates/world/2013_04_19_00_world_sai.sql new file mode 100644 index 00000000000..9ea635824ea --- /dev/null +++ b/sql/updates/world/2013_04_19_00_world_sai.sql @@ -0,0 +1,10 @@ +-- Event flag additions +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=0 AND `link`=1; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=1 AND `link`=0; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=2 AND `link`=3; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=3 AND `link`=0; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=4 AND `link`=5; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=5 AND `link`=0; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=6 AND `link`=7; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=7023 AND `source_type`=0 AND `id`=7 AND `link`=0; +UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=2244 AND `source_type`=0 AND `id`=11 AND `link`=12; diff --git a/sql/updates/world/2013_04_20_00_world_creature_loot_template.sql b/sql/updates/world/2013_04_20_00_world_creature_loot_template.sql new file mode 100644 index 00000000000..70bb2735f90 --- /dev/null +++ b/sql/updates/world/2013_04_20_00_world_creature_loot_template.sql @@ -0,0 +1,4 @@ +-- Insert Frozen Orb into The Prophet Tharon'ja's loot template +DELETE FROM `creature_loot_template` WHERE `entry`=31360 and `item`=43102; +INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(31360,43102,100,1,0,1,1); diff --git a/sql/updates/world/2013_04_20_01_world_conditions.sql b/sql/updates/world/2013_04_20_01_world_conditions.sql new file mode 100644 index 00000000000..3f4ce559256 --- /dev/null +++ b/sql/updates/world/2013_04_20_01_world_conditions.sql @@ -0,0 +1,38 @@ +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=23 AND `SourceGroup`=12944 AND `SourceEntry` IN (20761,17051,17022,17018,17023,19444); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=23 AND `SourceGroup`=12944 AND `SourceEntry` IN (19219,17017,17025,19330,19448,17059,17060,17049,19206); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=23 AND `SourceGroup`=12944 AND `SourceEntry` IN (19220,19332,19333,19331,19449,19209,19208,19207,17053,17052); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=23 AND `SourceGroup`=12944 AND `SourceEntry` IN (19211,19210,19212,20040); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Conditon rep Friendly +(23,12944,20761,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +(23,12944,17051,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +(23,12944,17022,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +(23,12944,17018,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +(23,12944,17023,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +(23,12944,19444,0,0,5,0,59,16|32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Friendly with Thorium Brotherhood'), +-- Conditon rep Honored +(23,12944,19219,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,17017,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,17025,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,19330,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,19448,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,17059,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,17060,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,17049,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +(23,12944,19206,0,0,5,0,59,32|64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Honored with Thorium Brotherhood'), +-- Conditon rep Revered +(23,12944,19220,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19332,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19333,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19331,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19449,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19209,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19208,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,19207,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,17053,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +(23,12944,17052,0,0,5,0,59,64|128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Revered with Thorium Brotherhood'), +-- Conditon rep Exalted +(23,12944,19211,0,0,5,0,59,128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Exalted with Thorium Brotherhood'), +(23,12944,19210,0,0,5,0,59,128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Exalted with Thorium Brotherhood'), +(23,12944,19212,0,0,5,0,59,128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Exalted with Thorium Brotherhood'), +(23,12944,20040,0,0,5,0,59,128,0,0,0, '', 'Lokhtos Darkbargainer - Only sell item if Exalted with Thorium Brotherhood'); diff --git a/sql/updates/world/2013_04_21_00_world_gameobject_loot_template.sql b/sql/updates/world/2013_04_21_00_world_gameobject_loot_template.sql new file mode 100644 index 00000000000..54b91b9fd44 --- /dev/null +++ b/sql/updates/world/2013_04_21_00_world_gameobject_loot_template.sql @@ -0,0 +1,23 @@ +-- Updating maxcount for Scarab Scarab Bag +UPDATE `item_loot_template` SET `maxcount`=5 WHERE `entry`=21156 AND `item` IN (20858,20859,20860,20861,20862,20863,20864,20865); +UPDATE `reference_loot_template` SET `maxcount`=2 WHERE `entry`=14001 AND `item` IN (20866,20867,20868,20869,20870,20871,20872,20873); +-- Updating loot for Scarab Coffer +DELETE FROM `gameobject_loot_template` WHERE `entry` IN (17532,17533); +INSERT INTO `gameobject_loot_template` VALUES +-- Scarab Coffer +(17532,21156,-100,1,0,1,1), -- Always drop a Sacrab Bag +(17532,1,100,1,0,-14001,1), -- Drop a AQ20 idol from reference +-- Large Scarab Coffer +(17533,21156,-100,1,0,1,1), -- Always drop a Sacrab Bag +(17533,1,100,1,0,-14502,1); -- Drop a AQ40 idol from reference +-- Updating loot for Large Scarab Coffer +DELETE FROM `reference_loot_template` WHERE `entry`=14502; +INSERT INTO `reference_loot_template` VALUES +(14502,20877,0,1,1,1,3), -- 1 to 3 Idol of the Sage +(14502,20879,0,1,1,1,3), -- 1 to 3 Idol of Life +(14502,20878,0,1,1,1,3), -- 1 to 3 Idol of Rebirth +(14502,20881,0,1,1,1,3), -- 1 to 3 Idol of Strife +(14502,20874,0,1,1,1,3), -- 1 to 3 Idol of the Sun +(14502,20882,0,1,1,1,3), -- 1 to 3 Idol of War +(14502,20876,0,1,1,1,3), -- 1 to 3 Idol of Death +(14502,20875,0,1,1,1,3); -- 1 to 3 Idol of Night diff --git a/sql/updates/world/2013_04_21_00_world_skinning_loot_template.sql b/sql/updates/world/2013_04_21_00_world_skinning_loot_template.sql new file mode 100644 index 00000000000..b9daf120d7a --- /dev/null +++ b/sql/updates/world/2013_04_21_00_world_skinning_loot_template.sql @@ -0,0 +1,7 @@ +-- Simplify skinloot for Axtroz and make sure something drops as well +UPDATE `skinning_loot_template` SET `ChanceOrQuestChance`=50 WHERE `entry`=12899 AND `item`=8170; +UPDATE `skinning_loot_template` SET `ChanceOrQuestChance`=35 WHERE `entry`=12899 AND `item`=15414; +UPDATE `skinning_loot_template` SET `ChanceOrQuestChance`=10 WHERE `entry`=12899 AND `item`=8165; +UPDATE `skinning_loot_template` SET `ChanceOrQuestChance`=0 WHERE `entry`=12899 AND `item`=4304; +-- Update dropchance for rare items on Axtroz +UPDATE `creature_loot_template` SET `ChanceOrQuestChance`=5 WHERE `entry`=12899 AND `mincountOrRef`=-24020; diff --git a/sql/updates/world/2013_04_21_01_world_gameobject_template.sql b/sql/updates/world/2013_04_21_01_world_gameobject_template.sql new file mode 100644 index 00000000000..6888545c123 --- /dev/null +++ b/sql/updates/world/2013_04_21_01_world_gameobject_template.sql @@ -0,0 +1,3 @@ +DELETE FROM `gameobject_template` WHERE `entry`=202193; +INSERT INTO `gameobject_template` (`entry`, `type`, `displayId`, `name`, `IconName`, `castBarCaption`, `unk1`, `faction`, `flags`, `size`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `data0`, `data1`, `data2`, `data3`, `data4`, `data5`, `data6`, `data7`, `data8`, `data9`, `data10`, `data11`, `data12`, `data13`, `data14`, `data15`, `data16`, `data17`, `data18`, `data19`, `data20`, `data21`, `data22`, `data23`, `AIName`, `ScriptName`, `WDBVerified`) VALUES +(202193, 5, 9050, 'Silver Covenant Banner', '', '', '', 0, 0, 0.8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 15595); diff --git a/sql/updates/world/2013_04_21_02_world_sai.sql b/sql/updates/world/2013_04_21_02_world_sai.sql new file mode 100644 index 00000000000..75dc64161ef --- /dev/null +++ b/sql/updates/world/2013_04_21_02_world_sai.sql @@ -0,0 +1,10 @@ +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=17210 AND `source_type`=0 AND `id`=2 AND `link`=3; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23619 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23623 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23624 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23625 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23626 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=0, `event_type`=0 WHERE `entryorguid`=83600 AND `source_type`=9 AND `id`=0 AND `link`=1; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=1173 AND `source_type`=0 AND `id`=8 AND `link`=9; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=23339 AND `source_type`=0 AND `id`=8 AND `link`=9; +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry` IN (10981,10982,10986,10987,10990,11602,11603,11605,11678,11839,12050,12051,12053,12127,13078,13080,13089,13097,13098,13179,13284,13316,13317,13326,13328,13396,13438,13442,13443,13447,13577,13797,13798,14283); diff --git a/sql/updates/world/2013_04_22_00_world_misc.sql b/sql/updates/world/2013_04_22_00_world_misc.sql new file mode 100644 index 00000000000..99eee20ffef --- /dev/null +++ b/sql/updates/world/2013_04_22_00_world_misc.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS ip2nation; +DROP TABLE IF EXISTS ip2nationCountries; + +DELETE FROM `command` WHERE `name` in ('account lock', 'account lock ip', 'account lock country'); +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('account lock ip', 0, 'Syntax: .account lock ip [on|off]\nAllow login from account only from current used IP or remove this requirement.'), +('account lock country', 0, 'Syntax: .account lock country [on|off]\nAllow login from account only from current used Country or remove this requirement.'); diff --git a/sql/updates/world/2013_04_27_00_world_misc.sql b/sql/updates/world/2013_04_27_00_world_misc.sql new file mode 100644 index 00000000000..4c7561a0e69 --- /dev/null +++ b/sql/updates/world/2013_04_27_00_world_misc.sql @@ -0,0 +1,10 @@ +DELETE FROM `command` WHERE `name` = 'guild rename'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('guild rename', 3, 'Syntax: .guild rename "$GuildName" "$NewGuildName" \n\n Rename a guild named $GuildName with $NewGuildName. Guild name and new guild name must in quotes.'); + +SET @ENTRY1 := 96; +SET @ENTRY2 := 97; +DELETE FROM `trinity_string` WHERE `entry` IN (@ENTRY1, @ENTRY2); +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(@ENTRY1, 'The guild name \'%s\' is already taken'), +(@ENTRY2, 'Changed guild name \'%s\' to \'%s\''); diff --git a/sql/updates/world/2013_04_27_01_world_misc.sql b/sql/updates/world/2013_04_27_01_world_misc.sql new file mode 100644 index 00000000000..c07a3f76b5f --- /dev/null +++ b/sql/updates/world/2013_04_27_01_world_misc.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `autobroadcast`; diff --git a/sql/updates/world/2013_04_29_00_world_misc.sql b/sql/updates/world/2013_04_29_00_world_misc.sql new file mode 100644 index 00000000000..716a77be584 --- /dev/null +++ b/sql/updates/world/2013_04_29_00_world_misc.sql @@ -0,0 +1,11 @@ +DELETE FROM `command` WHERE `name` = 'character rename'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('character rename', 2, 'Syntax: .character rename [$name] [$newName] \n\nMark selected in game or by $name in command character for rename at next login.\n\nIf $newName then the player will be forced rename.'); + +SET @ENTRY := 98; +SET @ENTRY1 := 167; +DELETE FROM `trinity_string` WHERE `entry` IN (@ENTRY, @ENTRY+1, @ENTRY1); +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(@ENTRY, '\'%s\' already exists as character name, choose another one'), +(@ENTRY+1, 'Player \'%s\' forced rename to \'%s\''), +(@ENTRY1, 'This name is reserved, choose another one'); diff --git a/sql/updates/world/2013_05_04_00_world_creature_template.sql b/sql/updates/world/2013_05_04_00_world_creature_template.sql new file mode 100644 index 00000000000..01037f835de --- /dev/null +++ b/sql/updates/world/2013_05_04_00_world_creature_template.sql @@ -0,0 +1,46 @@ +UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask` +|1 -- CHARM +|2 -- DISORIENTED +|4 -- DISARM +|8 -- DISTRACT +|16 -- FEAR +|32 -- GRIP +|64 -- ROOT +|256 -- SILENCE +|512 -- SLEEP +|1024 -- SNARE +|2048 -- STUN +|4096 -- FREEZE +|8192 -- KNOCKOUT +|65536 -- POLYMORPH +|131072 -- BANISH +|524288 -- SHACKLE +|4194304 -- TURN +|8388608 -- HORROR +|67108864 -- DAZE +|536870912 -- SAPPED +WHERE `entry` IN +(28859,31734, -- Malygos +39863,39864,39944,39945,40142,40143,40144,40145, -- Halion +39746,39805, -- General Zarithrian +39747,39823, -- Saviana Ragefire +39751,39899,39920,39922, -- Baltharus the Warborn +37025,38064,37217,38103, -- Stinky & Precious +10184,36538, -- Onyxia +33113,34003, -- Flame Leviathan +33293,33885, -- XT-002 Deconstructor +32857,33694, -- Stormcaller Brundir +32927,33692, -- Runemaster Molgeim +32867,33693, -- Steelbreaker +32930,33909, -- Kologarn +32933,32934, -- Kologarn Arms +33515,34175, -- Auriaya +32906,33360, -- Freya +32915,33391, -- Elder Brightleaf +32914,33393, -- Elder Stonebark +32913,33392, -- Elder Ironbranch +33350, -- Mimiron +32865,33147, -- Thorim +33271,33449, -- General Vezax +32871,33070, -- Algalon the Observer +33288,33955); -- Yogg-Saron diff --git a/sql/updates/world/2013_05_04_01_world_creature_template.sql b/sql/updates/world/2013_05_04_01_world_creature_template.sql new file mode 100644 index 00000000000..899a912fca5 --- /dev/null +++ b/sql/updates/world/2013_05_04_01_world_creature_template.sql @@ -0,0 +1,11 @@ +UPDATE `creature_text` SET `sound`=16912 WHERE `entry`=36494 AND `groupid`=0 AND `id`=0; +UPDATE `creature_text` SET `sound`=16916 WHERE `entry`=36494 AND `groupid`=1 AND `id`=0; +UPDATE `creature_text` SET `sound`=16917 WHERE `entry`=36494 AND `groupid`=2 AND `id`=0; +UPDATE `creature_text` SET `sound`=16915 WHERE `entry`=36494 AND `groupid`=3 AND `id`=0; +UPDATE `creature_text` SET `type`=14, `sound`=16913 WHERE `entry`=36494 AND `groupid`=4 AND `id`=0; +UPDATE `creature_text` SET `type`=14, `sound`=16914 WHERE `entry`=36494 AND `groupid`=4 AND `id`=1; +UPDATE `creature_text` SET `type`=42 WHERE `entry`=36494 AND `groupid`=5 AND `id`=0; + +DELETE FROM `creature_template_addon` WHERE `entry`=36494; +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(36494, 0, 0x0, 0x1, '68792'); diff --git a/sql/updates/world/2013_05_11_00_world_spell_target_position.sql b/sql/updates/world/2013_05_11_00_world_spell_target_position.sql new file mode 100644 index 00000000000..0e6b14682ae --- /dev/null +++ b/sql/updates/world/2013_05_11_00_world_spell_target_position.sql @@ -0,0 +1 @@ +UPDATE `spell_target_position` SET `target_map`=0 WHERE `id`=53821; diff --git a/sql/updates/world/2013_05_12_00_world_misc.sql b/sql/updates/world/2013_05_12_00_world_misc.sql new file mode 100644 index 00000000000..88e79b8a409 --- /dev/null +++ b/sql/updates/world/2013_05_12_00_world_misc.sql @@ -0,0 +1,198 @@ +DELETE FROM `creature` WHERE `guid` IN (116020,116021,116022,116023,116024,116025,116026,116029,116030,116031,116032,116033,116035,116037,116038,116039,116040,116042,116043,116044,116045,116046,116047,116049,116050,116051,116053,116054,116055,116056,116057,116058,116059,116060,116061,116065); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (47374,47469,47634,50546,50547,50548); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry` IN (47374,47469,47634); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorType`,`ScriptName`,`Comment`) VALUES +(13,1,47374,0,31,0,3,23837,0,0,'','Spell Ley Line Focus Control Ring targets ELM General Purpose Bunny'), +(13,1,47469,0,31,0,3,23837,0,0,'','Spell Ley Line Focus Control Amulet targets ELM General Purpose Bunny'), +(13,1,47634,0,31,0,3,23837,0,0,'','Spell Ley Line Focus Control Talisman targets ELM General Purpose Bunny'), +(13,1,50546,0,31,0,3,23837,0,0,'','Spell The Focus on the Beach: Ley Line Focus Control Ring Effect targets ELM General Purpose Bunny'), +(13,1,50547,0,31,0,3,23837,0,0,'','Spell Atop the Woodlands: Ley Line Focus Control Amulet Effect targets ELM General Purpose Bunny'), +(13,1,50548,0,31,0,3,23837,0,0,'','Spell The End of the Line: Ley Line Focus Control Talisman Effect targets ELM General Purpose Bunny'), +(17,0,47374,0,29,0,23837,7,0,97,'','Spell Ley Line Focus Control Ring can be casted only within 7y from ELM General Purpose Bunny'), +(17,0,47469,0,29,0,23837,7,0,97,'','Spell Ley Line Focus Control Amulet can be casted only within 7y from ELM General Purpose Bunny'), +(17,0,47634,0,29,0,23837,7,0,97,'','Spell Ley Line Focus Control Talisman can be casted only within 7y from ELM General Purpose Bunny'); + +DELETE FROM `creature_text` WHERE `entry` IN (26762,26815); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(26762,0,0,'Keep them away from the focus!',12,0,100,0,0,0,'Captain Emmy Malin'), +(26815,0,0,'Ya shouldn''a taken the boat north, mon!',12,0,100,0,0,0,'Lieutenant Ta''zinni'); + +DELETE FROM `spell_scripts` WHERE `id` IN (47393,47615,47638); +INSERT INTO `spell_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`) VALUES +(47393,0,14,47391,0,0,0,0,0,0), +(47615,0,14,47473,0,0,0,0,0,0), +(47638,0,14,47636,0,0,0,0,0,0); + +DELETE FROM `areatrigger_scripts` WHERE `entry`=4956; +INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES +(4956,'SmartTrigger'); + +UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=26873; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (26762,26815); +DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (26762,26815); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-98534,-98535,-98537,-98564,-98599,-98617,-115920,-115921,-115922,-115923,-115924,-115925,-115926,-115927,-115945,-115946,-115947,-115948,-115958,-115959,-115973,-115974,-115975,-115976,24021,26762,26815) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=4956 AND `source_type`=2; +DELETE FROM `smart_scripts` WHERE `entryorguid` BETWEEN 24021*100+0 AND 24021*100+16 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-98534,0,0,0,8,0,100,0,47469,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Amulet - Store targetlist'), +(-98534,0,1,0,8,0,100,0,50547,0,0,0,11,47472,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Atop the Woodlands: Ley Line Focus Control Amulet Effect - Spellcast Atop the Woodlands: Ley Line Focus Bunny Beam'), +(-98535,0,0,0,8,0,100,0,47469,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Amulet - Store targetlist'), +(-98535,0,1,0,8,0,100,0,50547,0,0,0,11,47472,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Atop the Woodlands: Ley Line Focus Control Amulet Effect - Spellcast Atop the Woodlands: Ley Line Focus Bunny Beam'), +(-98537,0,0,0,8,0,100,0,47374,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Ring - Store targetlist'), +(-98537,0,1,0,8,0,100,0,50546,0,0,0,11,47390,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit The Focus on the Beach: Ley Line Focus Control Ring Effect - Spellcast The Focus on the Beach: Ley Line Focus Bunny Beam'), +(-98564,0,0,0,8,0,100,0,47634,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Talisman - Store targetlist'), +(-98564,0,1,0,8,0,100,0,50548,0,0,0,11,47635,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit The End of the Line: Ley Line Focus Control Talisman Effect - Spellcast The End of the Line: Ley Line Focus Bunny Beam'), +(-98599,0,0,0,8,0,100,0,47374,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Ring - Store targetlist'), +(-98599,0,1,0,8,0,100,0,50546,0,0,0,11,47390,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit The Focus on the Beach: Ley Line Focus Control Ring Effect - Spellcast The Focus on the Beach: Ley Line Focus Bunny Beam'), +(-98617,0,0,0,8,0,100,0,47634,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit Ley Line Focus Control Talisman - Store targetlist'), +(-98617,0,1,0,8,0,100,0,50548,0,0,0,11,47635,0,0,0,0,0,12,1,0,0,0,0,0,0, 'ELM General Purpose Bunny - On spellhit The End of the Line: Ley Line Focus Control Talisman Effect - Spellcast The End of the Line: Ley Line Focus Bunny Beam'), + +(-115924,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115925,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115926,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115927,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115947,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115948,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+1,24021*100+2,24021*100+3,24021*100+4,24021*100+5,24021*100+6,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), + +(-115920,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115921,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115922,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115923,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115945,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115946,0,0,0,1,0,100,0,0,1000,20000,21000,87,24021*100+7,24021*100+8,24021*100+9,24021*100+10,24021*100+11,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), + +(-115958,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115959,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115973,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115974,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115975,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), +(-115976,0,0,0,1,0,100,0,0,1000,24000,25000,87,24021*100+12,24021*100+13,24021*100+14,24021*100+15,24021*100+16,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - On update OOC - Run random script'), + +(24021,0,0,0,54,0,100,0,0,0,0,0,80,24021*100+0,2,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large - Just summoned - Run script'), + +(26762,0,0,0,11,0,100,0,0,0,0,0,11,46906,0,0,0,0,0,10,115948,24021,0,0,0,0,0, 'Captain Emmy Malin - On spawn - Spellcast Surge Needle Beam'), +(26762,0,1,0,21,0,100,0,0,0,0,0,11,46906,0,0,0,0,0,10,115948,24021,0,0,0,0,0, 'Captain Emmy Malin - On homeposition reached - Spellcast Surge Needle Beam'), +(26762,0,2,0,9,0,100,0,0,40,3000,4000,11,20792,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Captain Emmy Malin - On target within 40y - Spellcast Frostbolt'), +(26762,0,3,0,0,0,100,0,7000,10000,9000,12000,11,49906,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Captain Emmy Malin - On update IC - Spellcast Ice Lance'), +(26762,0,4,0,9,0,100,0,0,5,9000,12000,11,11831,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Captain Emmy Malin - On target within 5y - Spellcast Frost Nova'), +(26762,0,5,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Captain Emmy Malin - On aggro - Say line'), + +(26815,0,0,0,9,0,100,0,0,40,3000,4000,11,51779,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Lieutenant Ta''zinni - On target within 40y - Spellcast Frostfirebolt'), +(26815,0,1,0,9,0,100,0,0,10,12000,18000,11,35250,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lieutenant Ta''zinni - On target within 10y - Spellcast Dragon''s Breath'), +(26815,0,2,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Lieutenant Ta''zinni - On aggro - Say line'), + +(4956,2,0,0,46,0,100,0,4956,0,0,0,33,26889,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Areatrigger Azure Dragonshire - On trigger - Quest credit'), + +(24021*100+0,9,0,0,0,0,100,0,0,0,0,0,11,47334,0,0,0,0,0,7,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large script 0 - Spellcast Ley Line Beam (no cast kit)'), +(24021*100+0,9,1,0,0,0,100,0,3000,4000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'ELM General Purpose Bunny Large script 0 - Despawn'), + +(24021*100+1,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3126.05,2140.401,17.8579,5.585053, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), +(24021*100+1,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3125.524,2146.786,15.84835,2.129302, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), +(24021*100+1,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3121.857,2144.208,19.87348,0.3141593, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), +(24021*100+1,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3131.571,2143.177,19.43405,0.4014257, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), +(24021*100+1,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3128.101,2141.035,17.94403,1.902409, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), +(24021*100+1,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3123.163,2141.134,16.98522,3.316126, 'ELM General Purpose Bunny Large script 1 - Summon ELM General Purpose Bunny Large'), + +(24021*100+2,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3125.091,2140.601,17.71151,2.443461, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), +(24021*100+2,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3132.777,2149.866,15.00388,5.986479, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), +(24021*100+2,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3127.046,2144.976,16.4135,5.183628, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), +(24021*100+2,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3122.372,2139.047,17.24562,5.009095, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), +(24021*100+2,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3126.123,2142.99,17.00723,2.792527, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), +(24021*100+2,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3128.526,2145.889,15.85672,0.2443461, 'ELM General Purpose Bunny Large script 2 - Summon ELM General Purpose Bunny Large'), + +(24021*100+3,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3126.866,2149.983,13.7796,1.832596, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), +(24021*100+3,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3131.825,2144.75,17.25836,1.570796, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), +(24021*100+3,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3121.043,2140.726,16.30317,4.24115, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), +(24021*100+3,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3129.281,2141.083,18.61101,3.124139, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), +(24021*100+3,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3125.717,2146.401,16.13597,5.72468, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), +(24021*100+3,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3123.911,2142.552,17.50746,4.380776, 'ELM General Purpose Bunny Large script 3 - Summon ELM General Purpose Bunny Large'), + +(24021*100+4,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3130.754,2151.47,14.37193,5.183628, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), +(24021*100+4,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3124.838,2143.604,17.12428,0.4014257, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), +(24021*100+4,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3127.993,2143.675,16.80205,5.148721, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), +(24021*100+4,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3121.175,2142.392,17.06362,0.9075712, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), +(24021*100+4,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3128.526,2145.889,15.85672,0.2443461, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), +(24021*100+4,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3134.843,2147.028,18.17949,5.864306, 'ELM General Purpose Bunny Large script 4 - Summon ELM General Purpose Bunny Large'), + +(24021*100+5,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3122.565,2142.866,17.20188,3.647738, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), +(24021*100+5,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3126.29,2142.063,17.4064,5.72468, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), +(24021*100+5,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3129.656,2149.474,14.7912,5.550147, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), +(24021*100+5,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3124.519,2149.514,14.5581,4.29351, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), +(24021*100+5,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3127.796,2138.372,19.97332,0.01745329, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), +(24021*100+5,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3132.397,2147.686,15.91525,0.9599311, 'ELM General Purpose Bunny Large script 5 - Summon ELM General Purpose Bunny Large'), + +(24021*100+6,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3131.072,2147.995,15.61533,1.466077, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), +(24021*100+6,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3128.782,2144.123,16.61955,5.742133, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), +(24021*100+6,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3123.601,2139.016,17.71019,0.4537856, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), +(24021*100+6,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3133.935,2143.841,21.74682,6.178465, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), +(24021*100+6,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3126.675,2146.103,16.11657,1.43117, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), +(24021*100+6,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3130.211,2145.085,16.58946,2.827433, 'ELM General Purpose Bunny Large script 6 - Summon ELM General Purpose Bunny Large'), + +(24021*100+7,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2894.85,1820.674,131.0997,1.012291, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), +(24021*100+7,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2891.408,1818.045,128.5932,0.541052, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), +(24021*100+7,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2888.546,1816.658,131.655,2.024582, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), +(24021*100+7,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2890.363,1810.202,129.936,0.7679449, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), +(24021*100+7,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2889.329,1822.168,130.1942,2.600541, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), +(24021*100+7,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2892.142,1809.754,129.4616,5.689773, 'ELM General Purpose Bunny Large script 7 - Summon ELM General Purpose Bunny Large'), + +(24021*100+8,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2894.762,1813.133,132.1913,1.256637, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), +(24021*100+8,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2888.24,1811.167,131.9773,3.473205, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), +(24021*100+8,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2891.765,1820.341,128.2378,2.443461, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), +(24021*100+8,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2889.968,1816.515,130.1833,3.577925, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), +(24021*100+8,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2895.262,1817.665,131.9376,4.415683, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), +(24021*100+8,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2892.956,1819.63,129.6165,3.106686, 'ELM General Purpose Bunny Large script 8 - Summon ELM General Purpose Bunny Large'), + +(24021*100+9,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2890.813,1812.197,129.4449,4.24115, 'ELM General Purpose Bunny Large script 9 - Summon ELM General Purpose Bunny Large'), +(24021*100+9,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2894.83,1810.606,132.5347,1.37881, 'ELM General Purpose Bunny Large script 9 - Summon ELM General Purpose Bunny Large'), +(24021*100+9,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2891.949,1816.533,128.7643,4.502949, 'ELM General Purpose Bunny Large script 9 - Summon ELM General Purpose Bunny Large'), +(24021*100+9,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2888.356,1820.349,131.507,3.839724, 'ELM General Purpose Bunny Large script 9 - Summon ELM General Purpose Bunny Large'), +(24021*100+9,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2893.333,1820.718,129.6705,1.48353, 'ELM General Purpose Bunny Large script 9 - Summon ELM General Purpose Bunny Large'), + +(24021*100+10,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2889.118,1823.984,130.3343,3.455752, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), +(24021*100+10,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2896.332,1820.913,131.8123,5.689773, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), +(24021*100+10,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2894.166,1819.122,130.8789,3.211406, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), +(24021*100+10,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2890.605,1822.912,128.89,1.762783, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), +(24021*100+10,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2888.642,1809.098,131.9985,3.385939, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), +(24021*100+10,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2892.705,1812.745,129.8363,1.308997, 'ELM General Purpose Bunny Large script 10 - Summon ELM General Purpose Bunny Large'), + +(24021*100+11,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2895.333,1822.925,131.1403,2.879793, 'ELM General Purpose Bunny Large script 11 - Summon ELM General Purpose Bunny Large'), +(24021*100+11,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2891.805,1822.136,128.129,6.161012, 'ELM General Purpose Bunny Large script 11 - Summon ELM General Purpose Bunny Large'), +(24021*100+11,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2894.475,1823.367,130.2928,1.937315, 'ELM General Purpose Bunny Large script 11 - Summon ELM General Purpose Bunny Large'), +(24021*100+11,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2889.26,1810.871,130.8892,0.8726646, 'ELM General Purpose Bunny Large script 11 - Summon ELM General Purpose Bunny Large'), +(24021*100+11,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,2893.049,1810.656,130.546,1.396263, 'ELM General Purpose Bunny Large script 11 - Summon ELM General Purpose Bunny Large'), + +(24021*100+12,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3057.062,1394.183,113.0584,5.8294, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), +(24021*100+12,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3054.48,1394.618,112.7426,1.762783, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), +(24021*100+12,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3060.249,1394.656,113.9411,0.3141593, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), +(24021*100+12,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3055.488,1393.478,112.698,3.141593, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), +(24021*100+12,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3061.458,1396.66,115.1446,0.1570796, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), +(24021*100+12,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3051.968,1401.044,116.3351,0.9424778, 'ELM General Purpose Bunny Large script 12 - Summon ELM General Purpose Bunny Large'), + +(24021*100+13,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3054.074,1397.247,113.4051,0.4712389, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), +(24021*100+13,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3057.188,1403.892,115.3656,4.380776, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), +(24021*100+13,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3052.451,1405.315,117.081,0.8552113, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), +(24021*100+13,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3059.104,1401.156,116.369,5.096361, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), +(24021*100+13,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3049.546,1404.567,114.6574,4.24115, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), +(24021*100+13,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3060.958,1399.016,117.6381,0.3665192, 'ELM General Purpose Bunny Large script 13 - Summon ELM General Purpose Bunny Large'), + +(24021*100+14,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3056.078,1396.021,113.2624,1.919862, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), +(24021*100+14,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3051.097,1400.683,119.1771,3.124139, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), +(24021*100+14,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3061.056,1398.113,116.3519,2.303835, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), +(24021*100+14,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3057.511,1398.638,114.0719,0.4886922, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), +(24021*100+14,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3055.962,1397.876,113.629,4.171337, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), +(24021*100+14,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3053.035,1396.689,115.7215,3.054326, 'ELM General Purpose Bunny Large script 14 - Summon ELM General Purpose Bunny Large'), + +(24021*100+15,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3054.111,1406.132,118.344,5.183628, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), +(24021*100+15,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3058.348,1399.74,114.4599,1.117011, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), +(24021*100+15,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3060.409,1401.954,119.1423,4.433136, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), +(24021*100+15,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3055.117,1405.109,116.396,1.867502, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), +(24021*100+15,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3051.709,1402.488,113.6939,5.009095, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), +(24021*100+15,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3059.448,1404.954,119.1292,4.712389, 'ELM General Purpose Bunny Large script 15 - Summon ELM General Purpose Bunny Large'), + +(24021*100+16,9,0,0,0,0,100,0,0,0,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3056.558,1406.72,119.7402,3.124139, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'), +(24021*100+16,9,1,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3052.471,1393.973,116.9445,5.637414, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'), +(24021*100+16,9,2,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3061.914,1394.956,114.8677,0.7853982, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'), +(24021*100+16,9,3,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3054.167,1403.503,114.3343,1.256637, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'), +(24021*100+16,9,4,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3049.392,1406.412,118.5037,2.80998, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'), +(24021*100+16,9,5,0,0,0,100,0,4000,4000,0,0,12,24021,8,4000,0,0,0,8,0,0,0,3057.68,1392.579,112.8306,2.792527, 'ELM General Purpose Bunny Large script 16 - Summon ELM General Purpose Bunny Large'); diff --git a/sql/updates/world/2013_05_13_00_world_spell_target_position.sql b/sql/updates/world/2013_05_13_00_world_spell_target_position.sql new file mode 100644 index 00000000000..c4ef5521094 --- /dev/null +++ b/sql/updates/world/2013_05_13_00_world_spell_target_position.sql @@ -0,0 +1,5 @@ +ALTER TABLE `spell_target_position` ADD COLUMN `effIndex` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`; +ALTER TABLE `spell_target_position` DROP INDEX `PRIMARY`, ADD PRIMARY KEY (`id`, `effIndex`); + +UPDATE `spell_target_position` SET `effIndex`='1' WHERE `id` IN (53821, 68081, 46473, 73655, 72546, 72340, 67838, 67835, 67836, 67837, 67834, 49098, 49097, 54963, 11012, 8606); +UPDATE `spell_target_position` SET `effIndex`='2' WHERE `id` IN (36801, 71765, 71763, 71762, 71744, 71712, 71751, 43209, 51852); diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index f7c4b9cb8ca..57ab1ffa4ed 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -98,7 +98,7 @@ endif() if( UNIX ) install(TARGETS authserver DESTINATION bin) - install(FILES authserver.conf.dist DESTINATION etc) + install(FILES authserver.conf.dist DESTINATION ${CONF_DIR}) elseif( WIN32 ) install(TARGETS authserver DESTINATION "${CMAKE_INSTALL_PREFIX}") install(FILES authserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}") diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 32ddf029f1c..a080a038314 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -386,17 +386,45 @@ bool AuthSocket::_HandleLogonChallenge() sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString()); sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Player address is '%s'", ip_address.c_str()); - if (strcmp(fields[3].GetCString(), ip_address.c_str())) + if (strcmp(fields[4].GetCString(), ip_address.c_str())) { sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP differs"); - pkt << (uint8) WOW_FAIL_SUSPENDED; + pkt << uint8(WOW_FAIL_LOCKED_ENFORCED); locked = true; } else sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP matches"); } else + { sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); + std::string accountCountry = fields[3].GetString(); + if (accountCountry.empty() || accountCountry == "00") + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to country", _login.c_str()); + else if (!accountCountry.empty()) + { + uint32 ip = inet_addr(ip_address.c_str()); + EndianConvertReverse(ip); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); + stmt->setUInt32(0, ip); + if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) + { + std::string loginCountry = (*sessionCountryQuery)[0].GetString(); + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _login.c_str(), accountCountry.c_str(), loginCountry.c_str()); + if (loginCountry != accountCountry) + { + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country differs."); + pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK); + locked = true; + } + else + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country matches"); + } + else + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] IP2NATION Table empty"); + } + } if (!locked) { @@ -426,8 +454,8 @@ bool AuthSocket::_HandleLogonChallenge() std::string rI = fields[0].GetString(); // Don't calculate (v, s) if there are already some in the database - std::string databaseV = fields[5].GetString(); - std::string databaseS = fields[6].GetString(); + std::string databaseV = fields[6].GetString(); + std::string databaseS = fields[7].GetString(); sLog->outDebug(LOG_FILTER_NETWORKIO, "database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str()); @@ -484,7 +512,7 @@ bool AuthSocket::_HandleLogonChallenge() if (securityFlags & 0x04) // Security token input pkt << uint8(1); - uint8 secLevel = fields[4].GetUInt8(); + uint8 secLevel = fields[5].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _localizationName.resize(4); @@ -498,7 +526,7 @@ bool AuthSocket::_HandleLogonChallenge() } } else //no account - pkt << (uint8)WOW_FAIL_UNKNOWN_ACCOUNT; + pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT); } socket().send((char const*)pkt.contents(), pkt.size()); diff --git a/src/server/game/AI/ScriptedAI/ScriptedGossip.h b/src/server/game/AI/ScriptedAI/ScriptedGossip.h index 80142afd14b..93add2ae652 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedGossip.h +++ b/src/server/game/AI/ScriptedAI/ScriptedGossip.h @@ -78,7 +78,11 @@ enum eTradeskill // d - Action (identifys this Menu Item) // e - Text to be displayed in pop up box // f - Money value in pop up box +// g - Coded +// h - Menu ID from DB +// i - Menu item ID from DB #define ADD_GOSSIP_ITEM(a, b, c, d) PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, a, b, c, d, "", 0) +#define ADD_GOSSIP_ITEM_DB(h, i, c, d) PlayerTalkClass->GetGossipMenu().AddMenuItem(h, i, c, d) #define ADD_GOSSIP_ITEM_EXTENDED(a, b, c, d, e, f, g) PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, a, b, c, d, e, f, g) // This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64) diff --git a/src/server/game/Addons/AddonMgr.cpp b/src/server/game/Addons/AddonMgr.cpp index 86a90d4d78a..3e1180727d0 100644 --- a/src/server/game/Addons/AddonMgr.cpp +++ b/src/server/game/Addons/AddonMgr.cpp @@ -18,10 +18,10 @@ #include "AddonMgr.h" #include "DatabaseEnv.h" +#include "DBCStores.h" #include "Log.h" #include "Timer.h" - -#include <list> +#include <openssl/md5.h> namespace AddonMgr { @@ -34,6 +34,8 @@ namespace typedef std::list<SavedAddon> SavedAddonsList; SavedAddonsList m_knownAddons; + + BannedAddonList m_bannedAddons; } void LoadFromDB() @@ -41,28 +43,57 @@ void LoadFromDB() uint32 oldMSTime = getMSTime(); QueryResult result = CharacterDatabase.Query("SELECT name, crc FROM addons"); - if (!result) + if (result) { - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 known addons. DB table `addons` is empty!"); - return; - } + uint32 count = 0; - uint32 count = 0; + do + { + Field* fields = result->Fetch(); - do - { - Field* fields = result->Fetch(); + std::string name = fields[0].GetString(); + uint32 crc = fields[1].GetUInt32(); - std::string name = fields[0].GetString(); - uint32 crc = fields[1].GetUInt32(); + m_knownAddons.push_back(SavedAddon(name, crc)); - m_knownAddons.push_back(SavedAddon(name, crc)); + ++count; + } + while (result->NextRow()); - ++count; + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u known addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } - while (result->NextRow()); + else + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 known addons. DB table `addons` is empty!"); + + oldMSTime = getMSTime(); + result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons"); + if (result) + { + uint32 count = 0; + uint32 dbcMaxBannedAddon = sBannedAddOnsStore.GetNumRows(); + + do + { + Field* fields = result->Fetch(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u known addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + BannedAddon addon; + addon.Id = fields[0].GetUInt32() + dbcMaxBannedAddon; + addon.Timestamp = uint32(fields[3].GetUInt64()); + + std::string name = fields[1].GetString(); + std::string version = fields[2].GetString(); + + MD5(reinterpret_cast<uint8 const*>(name.c_str()), name.length(), addon.NameMD5); + MD5(reinterpret_cast<uint8 const*>(version.c_str()), version.length(), addon.VersionMD5); + + m_bannedAddons.push_back(addon); + + ++count; + } + while (result->NextRow()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u banned addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + } } void SaveAddon(AddonInfo const& addon) @@ -91,4 +122,9 @@ SavedAddon const* GetAddonInfo(const std::string& name) return NULL; } +BannedAddonList const* GetBannedAddons() +{ + return &m_bannedAddons; +} + } // Namespace diff --git a/src/server/game/Addons/AddonMgr.h b/src/server/game/Addons/AddonMgr.h index 4d387fcfd4c..35e24e965b5 100644 --- a/src/server/game/Addons/AddonMgr.h +++ b/src/server/game/Addons/AddonMgr.h @@ -21,6 +21,7 @@ #include "Define.h" #include <string> +#include <list> struct AddonInfo { @@ -37,7 +38,7 @@ struct AddonInfo struct SavedAddon { - SavedAddon(const std::string& name, uint32 crc) : Name(name) + SavedAddon(std::string const& name, uint32 crc) : Name(name) { CRC = crc; } @@ -46,13 +47,24 @@ struct SavedAddon uint32 CRC; }; -#define STANDARD_ADDON_CRC 0x4c1c776d +struct BannedAddon +{ + uint32 Id; + uint8 NameMD5[16]; + uint8 VersionMD5[16]; + uint32 Timestamp; +}; + +#define STANDARD_ADDON_CRC 0x4C1C776D namespace AddonMgr { void LoadFromDB(); void SaveAddon(AddonInfo const& addon); SavedAddon const* GetAddonInfo(const std::string& name); + + typedef std::list<BannedAddon> BannedAddonList; + BannedAddonList const* GetBannedAddons(); } #endif diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index ed03d1e1d04..b5019037862 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -660,12 +660,12 @@ void AuctionEntry::SaveToDB(SQLTransaction& trans) const stmt->setUInt32(1, auctioneer); stmt->setUInt32(2, itemGUIDLow); stmt->setUInt32(3, owner); - stmt->setInt32 (4, int32(buyout)); - stmt->setUInt64(5, uint64(expire_time)); + stmt->setUInt32(4, buyout); + stmt->setUInt32(5, uint32(expire_time)); stmt->setUInt32(6, bidder); - stmt->setInt32 (7, int32(bid)); - stmt->setInt32 (8, int32(startbid)); - stmt->setInt32 (9, int32(deposit)); + stmt->setUInt32(7, bid); + stmt->setUInt32(8, startbid); + stmt->setUInt32(9, deposit); trans->Append(stmt); } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 047455ce8fb..e09ef0f1e05 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -171,13 +171,13 @@ enum WGGraveyardId enum WGGossipText { - BATTLEFIELD_WG_GOSSIPTEXT_GY_NE = -1850501, - BATTLEFIELD_WG_GOSSIPTEXT_GY_NW = -1850502, - BATTLEFIELD_WG_GOSSIPTEXT_GY_SE = -1850504, - BATTLEFIELD_WG_GOSSIPTEXT_GY_SW = -1850503, - BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP = -1850500, - BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE = -1850505, - BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE = -1850506 + BATTLEFIELD_WG_GOSSIPTEXT_GY_NE = 20071, + BATTLEFIELD_WG_GOSSIPTEXT_GY_NW = 20072, + BATTLEFIELD_WG_GOSSIPTEXT_GY_SE = 20074, + BATTLEFIELD_WG_GOSSIPTEXT_GY_SW = 20073, + BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP = 20070, + BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE = 20075, + BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE = 20076 }; enum WintergraspNpcs @@ -1127,7 +1127,7 @@ struct BfWGGameObjectBuilding build->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, NULL, true); if (build->GetEntry() == GO_WINTERGRASP_VAULT_GATE) if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) - go->EnableCollision(true); + go->SetGoState(GO_STATE_READY); // Update worldstate m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT - (m_Team * 3); @@ -1183,8 +1183,8 @@ struct BfWGGameObjectBuilding break; case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: if (GameObject* build = m_WG->GetGameObject(m_BuildGUID)) - if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 10.0f)) - go->EnableCollision(false); + if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) + go->SetGoState(GO_STATE_ACTIVE); m_WG->SetRelicInteractible(true); if (m_WG->GetRelic()) m_WG->GetRelic()->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 11df69b0d11..76bf3523af1 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -285,8 +285,6 @@ uint32 BattlegroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, Battleg //remove player from queue and from group info, if group info is empty then remove it too void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) { - //Player* player = ObjectAccessor::FindPlayer(guid); - int32 bracket_id = -1; // signed for proper for-loop finish QueuedPlayersMap::iterator itr; @@ -294,7 +292,10 @@ void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) itr = m_QueuedPlayers.find(guid); if (itr == m_QueuedPlayers.end()) { - sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue: couldn't find player to remove GUID: %u", GUID_LOPART(guid)); + std::string playerName = "Unknown"; + if (Player* player = ObjectAccessor::FindPlayer(guid)) + playerName = player->GetName(); + sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue: couldn't find player %s (GUID: %u)", playerName.c_str(), GUID_LOPART(guid)); return; } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp index 9d1c12a8903..c09b42f1e7f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp @@ -94,12 +94,6 @@ void BattlegroundBE::HandleKillPlayer(Player* player, Player* killer) CheckArenaWinConditions(); } -bool BattlegroundBE::HandlePlayerUnderMap(Player* player) -{ - player->TeleportTo(GetMapId(), 6238.930176f, 262.963470f, 0.889519f, player->GetOrientation()); - return true; -} - void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger) { if (GetStatus() != STATUS_IN_PROGRESS) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h index 9953e548df6..f9a3028ddf6 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h @@ -59,7 +59,6 @@ class BattlegroundBE : public Battleground void Reset(); void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player* killer); - bool HandlePlayerUnderMap(Player* player); /* Scorekeeping */ void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp index e7462f970a3..fe1973d3daf 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp @@ -201,12 +201,6 @@ void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger) } } -bool BattlegroundDS::HandlePlayerUnderMap(Player* player) -{ - player->TeleportTo(GetMapId(), 1299.046f, 784.825f, 9.338f, 2.422f); - return true; -} - void BattlegroundDS::FillInitialWorldStates(WorldPacket &data) { data << uint32(3610) << uint32(1); // 9 show diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h index 43437595220..cdfbbc480bb 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h @@ -96,7 +96,6 @@ class BattlegroundDS : public Battleground void Reset(); void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player* killer); - bool HandlePlayerUnderMap(Player* player); private: uint32 _waterfallTimer; uint8 _waterfallStatus; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp index 4d0cdf08eba..d3ce5c1544e 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp @@ -91,12 +91,6 @@ void BattlegroundNA::HandleKillPlayer(Player* player, Player* killer) CheckArenaWinConditions(); } -bool BattlegroundNA::HandlePlayerUnderMap(Player* player) -{ - player->TeleportTo(GetMapId(), 4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation()); - return true; -} - void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger) { if (GetStatus() != STATUS_IN_PROGRESS) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h index d53f47787a4..e3633197253 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h @@ -58,6 +58,5 @@ class BattlegroundNA : public Battleground void Reset(); void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player* killer); - bool HandlePlayerUnderMap(Player* player); }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp index 1b18583827d..de7d6995120 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp @@ -91,12 +91,6 @@ void BattlegroundRL::HandleKillPlayer(Player* player, Player* killer) CheckArenaWinConditions(); } -bool BattlegroundRL::HandlePlayerUnderMap(Player* player) -{ - player->TeleportTo(GetMapId(), 1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation()); - return true; -} - void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger) { if (GetStatus() != STATUS_IN_PROGRESS) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h index e5e55782005..877e0626271 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h @@ -54,6 +54,5 @@ class BattlegroundRL : public Battleground void HandleAreaTrigger(Player* Source, uint32 Trigger); bool SetupBattleground(); void HandleKillPlayer(Player* player, Player* killer); - bool HandlePlayerUnderMap(Player* player); }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp index 9f15bd29bed..68e961414f9 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp @@ -64,8 +64,6 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff) setState(BG_RV_STATE_SWITCH_PILLARS); break; case BG_RV_STATE_SWITCH_PILLARS: - for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) - DoorOpen(i); TogglePillarCollision(); setTimer(BG_RV_PILLAR_SWITCH_TIMER); break; @@ -135,12 +133,6 @@ void BattlegroundRV::HandleKillPlayer(Player* player, Player* killer) CheckArenaWinConditions(); } -bool BattlegroundRV::HandlePlayerUnderMap(Player* player) -{ - player->TeleportTo(GetMapId(), 763.5f, -284, 28.276f, 2.422f); - return true; -} - void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger) { if (GetStatus() != STATUS_IN_PROGRESS) @@ -217,6 +209,13 @@ void BattlegroundRV::TogglePillarCollision() { bool apply = GetPillarCollision(); + // Toggle visual pillars, pulley, gear, and collision based on previous state + for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_GEAR_2; ++i) + apply ? DoorOpen(i) : DoorClose(i); + + for (uint8 i = BG_RV_OBJECT_PILAR_2; i <= BG_RV_OBJECT_PULLEY_2; ++i) + apply ? DoorClose(i) : DoorOpen(i); + for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PILAR_COLLISION_4; ++i) { if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[i])) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h index b6dc3775df8..a836e4e1af3 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h @@ -108,7 +108,6 @@ class BattlegroundRV : public Battleground void HandleAreaTrigger(Player* Source, uint32 Trigger); bool SetupBattleground(); void HandleKillPlayer(Player* player, Player* killer); - bool HandlePlayerUnderMap(Player* player); private: uint32 Timer; diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 62a148eae03..5bede353783 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -369,8 +369,19 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co { Player* p = m_session->GetPlayer(); uint64 sel_guid = p->GetSelection(); - sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Account: %u) X: %f Y: %f Z: %f Map: %u Selected %s: %s (GUID: %u)]", - fullcmd.c_str(), p->GetName().c_str(), m_session->GetAccountId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), p->GetMapId(), + uint32 areaId = p->GetAreaId(); + std::string areaName = "Unknown"; + std::string zoneName = "Unknown"; + if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) + { + int locale = GetSessionDbcLocale(); + areaName = area->area_name[locale]; + if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) + zoneName = zone->area_name[locale]; + } + + sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Guid: %u) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected %s: %s (GUID: %u)]", + fullcmd.c_str(), p->GetName().c_str(), GUID_LOPART(p->GetGUID()), m_session->GetAccountId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), p->GetMapId(), p->GetMap() ? p->GetMap()->GetMapName() : "Unknown", areaId, areaName.c_str(), zoneName.c_str(), GetLogNameForGuid(sel_guid), (p->GetSelectedUnit()) ? p->GetSelectedUnit()->GetName().c_str() : "", GUID_LOPART(sel_guid)); } } diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 05c9c7b3b0e..6183ba8b8fa 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -63,6 +63,7 @@ DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt); DBCStorage <ArmorLocationEntry> sArmorLocationStore(ArmorLocationfmt); DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt); DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); +DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore(BannedAddOnsfmt); DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt); DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt); @@ -105,6 +106,7 @@ DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChance DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt); DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSpellCritfmt); +DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore(GtNPCManaCostScalerfmt); DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore(GtOCTClassCombatRatingScalarfmt); DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt); //DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently @@ -336,6 +338,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc");//15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sBannedAddOnsStore, dbcPath, "BannedAddOns.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");//15595 @@ -413,6 +416,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc");//15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sGtNPCManaCostScalerStore, dbcPath, "gtNPCManaCostScaler.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");//15595 //LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTHpPerStaminaStore, dbcPath, "gtOCTHpPerStamina.dbc");//15595 @@ -1055,6 +1059,7 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui return itr->second; } + uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId) { return PowersByClass[classId][powerType]; @@ -1212,3 +1217,18 @@ uint32 ScalingStatValuesEntry::GetDPSAndDamageMultiplier(uint32 subClass, bool i return 0; } +/// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery) +LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty) +{ + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) + { + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); + if (!dungeon) + continue; + + if (dungeon->map == mapId && Difficulty(dungeon->difficulty) == difficulty) + return dungeon; + } + + return NULL; +} diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 60ab87a2876..b49a1a96bd2 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -76,6 +76,7 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender); uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId); +LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); extern DBCStorage <AchievementEntry> sAchievementStore; extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; @@ -86,6 +87,7 @@ extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore; extern DBCStorage <ArmorLocationEntry> sArmorLocationStore; extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore; extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore; +extern DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore; extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore; extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore; extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; @@ -120,6 +122,7 @@ extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore; extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore; extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore; extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore; +extern DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore; extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore; //extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently extern DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index f1938dd0cd4..64c116654f4 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -630,6 +630,15 @@ struct BankBagSlotPricesEntry uint32 price; }; +struct BannedAddOnsEntry +{ + uint32 Id; + // uint32 NameMD5[4]; + // uint32 VersionMD5[4]; + // uint32 Timestamp; + // uint32 State; +}; + struct BarberShopStyleEntry { uint32 Id; // 0 @@ -1084,6 +1093,11 @@ struct GtChanceToSpellCritBaseEntry float base; }; +struct GtNPCManaCostScalerEntry +{ + float ratio; +}; + struct GtChanceToSpellCritEntry { float ratio; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 96da1add537..cc10199c240 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -33,6 +33,7 @@ char const AreaTriggerEntryfmt[] = "nifffxxxfffff"; char const ArmorLocationfmt[] = "nfffff"; char const AuctionHouseEntryfmt[] = "niiix"; char const BankBagSlotPricesEntryfmt[] = "ni"; +char const BannedAddOnsfmt[] = "nxxxxxxxxxx"; char const BarberShopStyleEntryfmt[] = "nixxxiii"; char const BattlemasterListEntryfmt[] = "niiiiiiiiixsiiiixxxx"; char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxii"; @@ -67,6 +68,7 @@ char const GtChanceToMeleeCritBasefmt[] = "xf"; char const GtChanceToMeleeCritfmt[] = "xf"; char const GtChanceToSpellCritBasefmt[] = "xf"; char const GtChanceToSpellCritfmt[] = "xf"; +char const GtNPCManaCostScalerfmt[] = "f"; char const GtOCTClassCombatRatingScalarfmt[] = "df"; char const GtOCTRegenHPfmt[] = "f"; //char const GtOCTRegenMPfmt[] = "f"; diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 3cd0a1223dd..02c09e0013d 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -65,6 +65,48 @@ void GossipMenu::AddMenuItem(int32 menuItemId, uint8 icon, std::string const& me menuItem.BoxMoney = boxMoney; } +/** + * @name AddMenuItem + * @brief Adds a localized gossip menu item from db by menu id and menu item id. + * @param menuId Gossip menu id. + * @param menuItemId Gossip menu item id. + * @param sender Identifier of the current menu. + * @param action Custom action given to OnGossipHello. + */ +void GossipMenu::AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action) +{ + /// Find items for given menu id. + GossipMenuItemsMapBounds bounds = sObjectMgr->GetGossipMenuItemsMapBounds(menuId); + /// Return if there are none. + if (bounds.first == bounds.second) + return; + + /// Iterate over each of them. + for (GossipMenuItemsContainer::const_iterator itr = bounds.first; itr != bounds.second; ++itr) + { + /// Find the one with the given menu item id. + if (itr->second.OptionIndex != menuItemId) + continue; + + /// Store texts for localization. + std::string strOptionText = itr->second.OptionText; + std::string strBoxText = itr->second.BoxText; + + /// Check need of localization. + if (GetLocale() > LOCALE_enUS) + /// Find localizations from database. + if (GossipMenuItemsLocale const* no = sObjectMgr->GetGossipMenuItemsLocale(MAKE_PAIR32(menuId, menuItemId))) + { + /// Translate texts if there are any. + ObjectMgr::GetLocaleString(no->OptionText, GetLocale(), strOptionText); + ObjectMgr::GetLocaleString(no->BoxText, GetLocale(), strBoxText); + } + + /// Add menu item with existing method. Menu item id -1 is also used in ADD_GOSSIP_ITEM macro. + AddMenuItem(-1, itr->second.OptionIcon, strOptionText, sender, action, strBoxText, itr->second.BoxMoney, itr->second.BoxCoded); + } +} + void GossipMenu::AddGossipMenuItemData(uint32 menuItemId, uint32 gossipActionMenuId, uint32 gossipActionPoi) { GossipMenuItemData& itemData = _menuItemData[menuItemId]; @@ -108,6 +150,8 @@ void GossipMenu::ClearMenu() PlayerMenu::PlayerMenu(WorldSession* session) : _session(session) { + if (_session) + _gossipMenu.SetLocale(_session->GetSessionDbLocaleIndex()); } PlayerMenu::~PlayerMenu() diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h index 7d6d21cd9ad..c76febc0165 100644 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -163,9 +163,12 @@ class GossipMenu ~GossipMenu(); void AddMenuItem(int32 menuItemId, uint8 icon, std::string const& message, uint32 sender, uint32 action, std::string const& boxMessage, uint32 boxMoney, bool coded = false); + void AddMenuItem(uint32 menuId, uint32 menuItemId, uint32 sender, uint32 action); void SetMenuId(uint32 menu_id) { _menuId = menu_id; } uint32 GetMenuId() const { return _menuId; } + void SetLocale(LocaleConstant locale) { _locale = locale; } + LocaleConstant GetLocale() const { return _locale; } void AddGossipMenuItemData(uint32 menuItemId, uint32 gossipActionMenuId, uint32 gossipActionPoi); @@ -212,6 +215,7 @@ class GossipMenu GossipMenuItemContainer _menuItems; GossipMenuItemDataContainer _menuItemData; uint32 _menuId; + LocaleConstant _locale; }; class QuestMenu diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 7ac40ad08a0..a1665b9c48f 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1120,7 +1120,7 @@ void GameObject::Use(Unit* user) Player* player = user->ToPlayer(); - player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID); + player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID, true); player->SendPreparedGossip(this); return; } @@ -1832,14 +1832,14 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= NULL*/, u Player* player = attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself(); // dealing damage, send packet - /// @todo is there any packet for healing? - if (change < 0 && player) + if (player) { WorldPacket data(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, 8 + 8 + 8 + 4 + 4); data.appendPackGUID(GetGUID()); data.appendPackGUID(attackerOrHealer->GetGUID()); data.appendPackGUID(player->GetGUID()); - data << uint32(-change); + data << uint32(-change); // change < 0 triggers SPELL_BUILDING_HEAL combat log event + // change >= 0 triggers SPELL_BUILDING_DAMAGE event data << uint32(spellId); player->GetSession()->SendPacket(&data); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ab8f9690b5e..5838786bc3e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4723,7 +4723,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell /** * Deletes a character from the database * - * The way, how the characters will be deleted is decided based on the config option. + * The way characters will be deleted is decided based on the config option. * * @see Player::DeleteOldCharacters * @@ -4734,19 +4734,32 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell */ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmChars, bool deleteFinally) { - // for not existed account avoid update realm + // Avoid realm-update for non-existing account if (accountId == 0) updateRealmChars = false; + // Convert guid to low GUID for CharacterNameData, but also other methods on success + uint32 guid = GUID_LOPART(playerguid); uint32 charDelete_method = sWorld->getIntConfig(CONFIG_CHARDELETE_METHOD); - uint32 charDelete_minLvl = sWorld->getIntConfig(CONFIG_CHARDELETE_MIN_LEVEL); - // if we want to finally delete the character or the character does not meet the level requirement, - // we set it to mode CHAR_DELETE_REMOVE - if (deleteFinally || Player::GetLevelFromDB(playerguid) < charDelete_minLvl) + if (deleteFinally) charDelete_method = CHAR_DELETE_REMOVE; + else if (CharacterNameData const* nameData = sWorld->GetCharacterNameData(guid)) // To avoid a query, we select loaded data. If it doesn't exist, return. + { + if (!nameData) + { + sLog->outError(LOG_FILTER_PLAYER, "Cannot find CharacterNameData entry for player %u from account %u. Could not delete character.", guid, accountId); + return; + } - uint32 guid = GUID_LOPART(playerguid); + // Define the required variables + uint32 charDelete_minLvl = sWorld->getIntConfig(nameData->m_class != CLASS_DEATH_KNIGHT ? CONFIG_CHARDELETE_MIN_LEVEL : CONFIG_CHARDELETE_HEROIC_MIN_LEVEL); + + // if we want to finalize the character removal or the character does not meet the level requirement of either heroic or non-heroic settings, + // we set it to mode CHAR_DELETE_REMOVE + if (nameData->m_level < charDelete_minLvl) + charDelete_method = CHAR_DELETE_REMOVE; + } // convert corpse to bones if exist (to prevent exiting Corpse in World without DB entry) // bones will be deleted by corpse/bones deleting thread shortly @@ -5046,10 +5059,13 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } default: sLog->outError(LOG_FILTER_PLAYER, "Player::DeleteFromDB: Unsupported delete method: %u.", charDelete_method); + return; } if (updateRealmChars) sWorld->UpdateRealmCharCount(accountId); + + sWorld->DeleteCharacterNameData(guid); } /** @@ -6626,13 +6642,13 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) { if (button >= MAX_ACTION_BUTTONS) { - sLog->outError(LOG_FILTER_PLAYER, "Action %u not added into button %u for player %s: button must be < %u", action, button, GetName().c_str(), MAX_ACTION_BUTTONS ); + sLog->outError(LOG_FILTER_PLAYER, "Action %u not added into button %u for player %s (GUID: %u): button must be < %u", action, button, GetName().c_str(), GUID_LOPART(GetGUID()), MAX_ACTION_BUTTONS ); return false; } if (action >= MAX_ACTION_BUTTON_ACTION_VALUE) { - sLog->outError(LOG_FILTER_PLAYER, "Action %u not added into button %u for player %s: action must be < %u", action, button, GetName().c_str(), MAX_ACTION_BUTTON_ACTION_VALUE); + sLog->outError(LOG_FILTER_PLAYER, "Action %u not added into button %u for player %s (GUID: %u): action must be < %u", action, button, GetName().c_str(), GUID_LOPART(GetGUID()), MAX_ACTION_BUTTON_ACTION_VALUE); return false; } @@ -6641,20 +6657,20 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) case ACTION_BUTTON_SPELL: if (!sSpellMgr->GetSpellInfo(action)) { - sLog->outError(LOG_FILTER_PLAYER, "Spell action %u not added into button %u for player %s: spell not exist", action, button, GetName().c_str()); + sLog->outError(LOG_FILTER_PLAYER, "Spell action %u not added into button %u for player %s (GUID: %u): spell not exist", action, button, GetName().c_str(), GUID_LOPART(GetGUID())); return false; } if (!HasSpell(action)) { - sLog->outError(LOG_FILTER_PLAYER, "Spell action %u not added into button %u for player %s: player don't known this spell", action, button, GetName().c_str()); + sLog->outError(LOG_FILTER_PLAYER, "Spell action %u not added into button %u for player %s (GUID: %u): player don't known this spell", action, button, GetName().c_str(), GUID_LOPART(GetGUID())); return false; } break; case ACTION_BUTTON_ITEM: if (!sObjectMgr->GetItemTemplate(action)) { - sLog->outError(LOG_FILTER_PLAYER, "Item action %u not added into button %u for player %s: item not exist", action, button, GetName().c_str()); + sLog->outError(LOG_FILTER_PLAYER, "Item action %u not added into button %u for player %s (GUID: %u): item not exist", action, button, GetName().c_str(), GUID_LOPART(GetGUID())); return false; } break; @@ -6992,14 +7008,11 @@ void Player::RewardReputation(Unit* victim, float rate) if (GetChampioningFaction()) { // support for: Championing - http://www.wowwiki.com/Championing - Map const* map = GetMap(); if (map && map->IsNonRaidDungeon()) - { - if (AccessRequirement const* accessRequirement = sObjectMgr->GetAccessRequirement(map->GetId(), map->GetDifficulty())) - if (accessRequirement->levelMin == 80) + if (LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty())) + if (dungeon->reclevel == 80) ChampioningFaction = GetChampioningFaction(); - } } uint32 team = GetTeam(); @@ -14363,12 +14376,11 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool if (source->GetTypeId() == TYPEID_UNIT) { npcflags = source->GetUInt32Value(UNIT_NPC_FLAGS); - if (npcflags & UNIT_NPC_FLAG_QUESTGIVER && showQuests) + if (showQuests && npcflags & UNIT_NPC_FLAG_QUESTGIVER) PrepareQuestMenu(source->GetGUID()); } - - if (source->GetTypeId() == TYPEID_GAMEOBJECT) - if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + else if (source->GetTypeId() == TYPEID_GAMEOBJECT) + if (showQuests && source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) PrepareQuestMenu(source->GetGUID()); for (GossipMenuItemsContainer::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) @@ -17007,7 +17019,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM); if (!result) { - sLog->outError(LOG_FILTER_PLAYER, "Player (GUID: %u) not found in table `characters`, can't load. ", guid); + std::string name = "<unknown>"; + sObjectMgr->GetPlayerNameByGUID(guid, name); + sLog->outError(LOG_FILTER_PLAYER, "Player %s (GUID: %u) not found in table `characters`, can't load. ", name.c_str(), guid); return false; } @@ -18636,14 +18650,16 @@ void Player::_LoadBoundInstances(PreparedQueryResult result) bool deleteInstance = false; MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); + std::string mapname = mapEntry ? mapEntry->name : "Unknown"; + if (!mapEntry || !mapEntry->IsDungeon()) { - sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d", GetName().c_str(), GetGUIDLow(), mapId); + sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d (%s)", GetName().c_str(), GetGUIDLow(), mapId, mapname.c_str()); deleteInstance = true; } else if (difficulty >= MAX_DIFFICULTY) { - sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName().c_str(), GetGUIDLow(), difficulty, mapId); + sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUIDLow(), difficulty, mapId, mapname.c_str()); deleteInstance = true; } else @@ -18651,12 +18667,12 @@ void Player::_LoadBoundInstances(PreparedQueryResult result) MapDifficulty const* mapDiff = GetMapDifficultyData(mapId, Difficulty(difficulty)); if (!mapDiff) { - sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName().c_str(), GetGUIDLow(), difficulty, mapId); + sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u (%s)", GetName().c_str(), GetGUIDLow(), difficulty, mapId, mapname.c_str()); deleteInstance = true; } else if (!perm && group) { - sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d, %d, %d", GetName().c_str(), GetGUIDLow(), GUID_LOPART(group->GetGUID()), mapId, instanceId, difficulty); + sLog->outError(LOG_FILTER_PLAYER, "_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d (%s), %d, %d", GetName().c_str(), GetGUIDLow(), GUID_LOPART(group->GetGUID()), mapId, mapname.c_str(), instanceId, difficulty); deleteInstance = true; } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6fb43f44a3c..ad66f5a7e6c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -145,37 +145,30 @@ void DamageInfo::BlockDamage(uint32 amount) m_damage -= amount; } -ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo) -:_actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask), -_hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo) -{ -} +ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, + uint32 typeMask, uint32 spellTypeMask, + uint32 spellPhaseMask, uint32 hitMask, + Spell* spell, DamageInfo* damageInfo, + HealInfo* healInfo) : + _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), + _typeMask(typeMask), _spellTypeMask(spellTypeMask), + _spellPhaseMask(spellPhaseMask), _hitMask(hitMask), _spell(spell), + _damageInfo(damageInfo), _healInfo(healInfo) +{ } // we can disable this warning for this since it only // causes undefined behavior when passed to the base class constructor #ifdef _MSC_VER #pragma warning(disable:4355) #endif -Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject), - m_movedPlayer(NULL), - m_lastSanctuaryTime(0), - m_TempSpeed(0.0f), - IsAIEnabled(false), - NeedChangeAI(false), - m_ControlledByPlayer(false), - movespline(new Movement::MoveSpline()), - i_AI(NULL), - i_disabledAI(NULL), - m_AutoRepeatFirstCast(false), - m_procDeep(0), - m_removedAurasCount(0), - i_motionMaster(this), - m_ThreatManager(this), - m_vehicle(NULL), - m_vehicleKit(NULL), - m_unitTypeMask(UNIT_MASK_NONE), - m_HostileRefManager(this), - _lastDamagedTime(0) +Unit::Unit(bool isWorldObject) : + WorldObject(isWorldObject), m_movedPlayer(NULL), m_lastSanctuaryTime(0), + m_TempSpeed(0.0f), IsAIEnabled(false), NeedChangeAI(false), + m_ControlledByPlayer(false), movespline(new Movement::MoveSpline()), + i_AI(NULL), i_disabledAI(NULL), m_AutoRepeatFirstCast(false), m_procDeep(0), + m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), + m_vehicle(NULL), m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), + m_HostileRefManager(this), _lastDamagedTime(0) { #ifdef _MSC_VER #pragma warning(default:4355) @@ -1442,7 +1435,6 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType /*attackType*/) { - uint32 newdamage = 0; float armor = float(victim->GetArmor()); // bypass enemy armor by SPELL_AURA_BYPASS_ARMOR_FOR_CASTER @@ -1460,8 +1452,8 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor); - AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); - for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) + AuraEffectList const& resIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffectList::const_iterator j = resIgnoreAuras.begin(); j != resIgnoreAuras.end(); ++j) { if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) armor = floor(AddPct(armor, -(*j)->GetAmount())); @@ -1489,7 +1481,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo float levelModifier = getLevel(); if (levelModifier > 59) - levelModifier = levelModifier + (4.5f * (levelModifier - 59)); + levelModifier = levelModifier + 4.5f * (levelModifier - 59); float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40); tmpvalue = tmpvalue / (1.0f + tmpvalue); @@ -1499,9 +1491,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo if (tmpvalue > 0.75f) tmpvalue = 0.75f; - newdamage = uint32(damage - (damage * tmpvalue)); - - return (newdamage > 1) ? newdamage : 1; + return std::max<uint32>(damage * (1.0f - tmpvalue), 1); } void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32 *absorb, uint32 *resist, SpellInfo const* spellInfo) @@ -1589,6 +1579,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectingSpell(spellInfo)) auraAbsorbMod = float((*itr)->GetAmount()); } + RoundToInterval(auraAbsorbMod, 0.0f, 100.0f); // We're going to call functions which can modify content of the list during iteration over it's elements @@ -1710,7 +1701,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe // We're going to call functions which can modify content of the list during iteration over it's elements // Let's copy the list so we can prevent iterator invalidation AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT)); - for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr) + for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr) { // Check if aura was removed during iteration - we don't need to work on such auras AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID()); @@ -2147,7 +2138,7 @@ bool Unit::isBlockCritical() return false; } -int32 Unit::GetMechanicResistChance(const SpellInfo* spell) +int32 Unit::GetMechanicResistChance(const SpellInfo* spell) const { if (!spell) return 0; @@ -2171,11 +2162,15 @@ bool Unit::CanUseAttackType(uint8 attacktype) const { switch (attacktype) { - case BASE_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - case OFF_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_OFFHAND); - case RANGED_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED); + case BASE_ATTACK: + return !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + case OFF_ATTACK: + return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_OFFHAND); + case RANGED_ATTACK: + return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED); + default: + return true; } - return true; } // Melee based spells hit result calculations @@ -4106,11 +4101,11 @@ bool Unit::HasAuraTypeWithValue(AuraType auratype, int32 value) const return false; } -bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid) +bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid) const { if (!(m_interruptMask & flag)) return false; - for (AuraApplicationList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); ++iter) + for (AuraApplicationList::const_iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); ++iter) { if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellInfo()->AuraInterruptFlags & flag && (!guid || (*iter)->GetBase()->GetCasterGUID() == guid)) return true; @@ -4118,9 +4113,9 @@ bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid) return false; } -bool Unit::HasNegativeAuraWithAttribute(uint32 flag, uint64 guid) +bool Unit::HasNegativeAuraWithAttribute(uint32 flag, uint64 guid) const { - for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) + for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) { Aura const* aura = iter->second->GetBase(); if (!iter->second->IsPositive() && aura->GetSpellInfo()->Attributes & flag && (!guid || aura->GetCasterGUID() == guid)) @@ -4129,11 +4124,11 @@ bool Unit::HasNegativeAuraWithAttribute(uint32 flag, uint64 guid) return false; } -bool Unit::HasAuraWithMechanic(uint32 mechanicMask) +bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const { - for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) + for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) { - SpellInfo const* spellInfo = iter->second->GetBase()->GetSpellInfo(); + SpellInfo const* spellInfo = iter->second->GetBase()->GetSpellInfo(); if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic))) return true; @@ -4168,7 +4163,7 @@ uint32 Unit::GetDiseasesByCaster(uint64 casterGUID, bool remove) }; uint32 diseases = 0; - for (AuraType const* itr = &diseaseAuraTypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr) + for (AuraType const* itr = diseaseAuraTypes; *itr != SPELL_AURA_NONE; ++itr) { for (AuraEffectList::iterator i = m_modAuras[*itr].begin(); i != m_modAuras[*itr].end();) { @@ -8648,9 +8643,11 @@ void Unit::SetCharm(Unit* charm, bool apply) } if (charm->GetTypeId() == TYPEID_PLAYER - || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) - || charm->GetOwnerGUID() != GetGUID()) + || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) + || charm->GetOwnerGUID() != GetGUID()) + { m_Controlled.erase(charm); + } } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 8bedb7b231d..396a4c577f1 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1474,19 +1474,19 @@ class Unit : public WorldObject uint32 GetCritDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_CRIT_TAKEN, 2.2f, 33.0f, damage); } uint32 GetDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN, 2.0f, 100.0f, damage); } - void ApplyResilience(const Unit* victim, int32 * damage, bool isCrit) const; + void ApplyResilience(Unit const* victim, int32 * damage, bool isCrit) const; - float MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, uint32 spellId) const; + float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const; SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell); SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell); SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false); - float GetUnitDodgeChance() const; - float GetUnitParryChance() const; - float GetUnitBlockChance() const; - float GetUnitMissChance(WeaponAttackType attType) const; + float GetUnitDodgeChance() const; + float GetUnitParryChance() const; + float GetUnitBlockChance() const; + float GetUnitMissChance(WeaponAttackType attType) const; float GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const; - int32 GetMechanicResistChance(const SpellInfo* spell); + int32 GetMechanicResistChance(const SpellInfo* spell) const; bool CanUseAttackType(uint8 attacktype) const; virtual uint32 GetBlockPercent() const { return 30; } @@ -1784,9 +1784,9 @@ class Unit : public WorldObject bool HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const; bool HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const; bool HasAuraTypeWithValue(AuraType auratype, int32 value) const; - bool HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid = 0); - bool HasNegativeAuraWithAttribute(uint32 flag, uint64 guid = 0); - bool HasAuraWithMechanic(uint32 mechanicMask); + bool HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid = 0) const; + bool HasNegativeAuraWithAttribute(uint32 flag, uint64 guid = 0) const; + bool HasAuraWithMechanic(uint32 mechanicMask) const; AuraEffect* IsScriptOverriden(SpellInfo const* spell, int32 script) const; uint32 GetDiseasesByCaster(uint64 casterGUID, bool remove = false); diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 1b4f687d8c5..e727977df19 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -205,8 +205,8 @@ void GameEventMgr::LoadFromDB() { { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 7 - QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, description, world_event FROM game_event"); + // 0 1 2 3 4 5 6 7 8 + QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, description, world_event, announce FROM game_event"); if (!result) { mGameEvent.clear(); @@ -237,6 +237,7 @@ void GameEventMgr::LoadFromDB() pGameEvent.state = (GameEventState)(fields[7].GetUInt8()); pGameEvent.nextstart = 0; + pGameEvent.announce = fields[8].GetUInt8(); if (pGameEvent.length == 0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check { @@ -1105,7 +1106,8 @@ void GameEventMgr::UnApplyEvent(uint16 event_id) void GameEventMgr::ApplyNewEvent(uint16 event_id) { - if (sWorld->getBoolConfig(CONFIG_EVENT_ANNOUNCE)) + uint8 announce = mGameEvent[event_id].announce; + if (announce == 1 || (announce == 2 && sWorld->getBoolConfig(CONFIG_EVENT_ANNOUNCE))) sWorld->SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str()); sLog->outInfo(LOG_FILTER_GAMEEVENTS, "GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str()); diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index 192c441f50f..994f32f75d6 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -66,6 +66,7 @@ struct GameEventData GameEventConditionMap conditions; // conditions to finish std::set<uint16 /*gameevent id*/> prerequisite_events; // events that must be completed before starting this event std::string description; + uint8 announce; // if 0 dont announce, if 1 announce, if 2 take config value bool isValid() const { return length > 0 || state > GAMEEVENT_NORMAL; } }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 7982b8486b4..c6c239b6518 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7930,13 +7930,13 @@ void ObjectMgr::AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, CreatureTemplate const* cInfo = GetCreatureTemplate(entry); if (!cInfo) { - sLog->outError(LOG_FILTER_SQL, "Table `npc_trainer` contains an entry for a non-existing creature template (Entry: %u), ignoring", entry); + sLog->outError(LOG_FILTER_SQL, "Table `npc_trainer` contains entries for a non-existing creature template (Entry: %u), ignoring", entry); return; } if (!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER)) { - sLog->outError(LOG_FILTER_SQL, "Table `npc_trainer` contains an entry for a creature template (Entry: %u) without trainer flag, ignoring", entry); + sLog->outError(LOG_FILTER_SQL, "Table `npc_trainer` contains entries for a creature template (Entry: %u) without trainer flag, ignoring", entry); return; } diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index f559e581dd8..41d81dc39d2 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1022,10 +1022,10 @@ void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const if (!pFrom->IsBank() && m_pPlayer->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE)) /// @todo Move this to scripts { sLog->outCommand(m_pPlayer->GetSession()->GetAccountId(), - "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)", - m_pPlayer->GetName().c_str(), m_pPlayer->GetSession()->GetAccountId(), + "GM %s (Guid: %u) (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank named: %s (Guild ID: %u)", + m_pPlayer->GetName().c_str(), m_pPlayer->GetGUIDLow(), m_pPlayer->GetSession()->GetAccountId(), pFrom->GetItem()->GetTemplate()->Name1.c_str(), pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(), - m_pGuild->GetId()); + m_pGuild->GetName().c_str(), m_pGuild->GetId()); } } @@ -1356,6 +1356,19 @@ void Guild::OnPlayerStatusChange(Player* player, uint32 flag, bool state) } } +bool Guild::SetName(std::string const& name) +{ + if (m_name == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) + return false; + + m_name = name; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_NAME); + stmt->setString(0, m_name); + stmt->setUInt32(1, GetId()); + CharacterDatabase.Execute(stmt); + return true; +} + void Guild::HandleRoster(WorldSession* session /*= NULL*/) { ByteBuffer memberData(100); diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 0c41cc68a60..cf03cb58748 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -768,6 +768,8 @@ public: std::string const& GetMOTD() const { return m_motd; } std::string const& GetInfo() const { return m_info; } + bool SetName(std::string const& name); + // Handle client commands void HandleRoster(WorldSession* session = NULL); void HandleQuery(WorldSession* session); diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 33316338c9e..3fc36cf6f7c 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -151,6 +151,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) if (itemsCount > MAX_AUCTION_ITEMS) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); + recvData.rfinish(); return; } @@ -159,8 +160,11 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) recvData >> itemGUIDs[i]; recvData >> count[i]; - if (!itemGUIDs[i] || !count[i] || count[i] > 1000 ) + if (!itemGUIDs[i] || !count[i] || count[i] > 1000) + { + recvData.rfinish(); return; + } } recvData >> bid; @@ -170,6 +174,14 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) if (!bid || !etime) return; + if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUIDLow()); + SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); + return; + } + + Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 8ad49724b2e..ea8fd5a9d9d 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -763,7 +763,6 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) std::string IP_str = GetRemoteAddress(); sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d, IP: %s deleted character: %s, GUID: %u, Level: %u", accountId, IP_str.c_str(), name.c_str(), GUID_LOPART(guid), level); sScriptMgr->OnPlayerDelete(guid); - sWorld->DeleteCharacterNameData(GUID_LOPART(guid)); if (sLog->ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO)) // optimize GetPlayerDump call { diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index ee28e0c30d5..d1a8bb8c3e5 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -942,10 +942,28 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke { if (player) { + uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) - *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); - else - *data << uint16(MEMBER_STATUS_ONLINE); + playerStatus |= MEMBER_STATUS_PVP; + + if (!player->isAlive()) + { + if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + playerStatus |= MEMBER_STATUS_GHOST; + else + playerStatus |= MEMBER_STATUS_DEAD; + } + + if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + playerStatus |= MEMBER_STATUS_PVP_FFA; + + if (player->isAFK()) + playerStatus |= MEMBER_STATUS_AFK; + + if (player->isDND()) + playerStatus |= MEMBER_STATUS_DND; + + *data << uint16(playerStatus); } else *data << uint16(MEMBER_STATUS_OFFLINE); @@ -977,7 +995,11 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint16(0); if (mask & GROUP_UPDATE_FLAG_POSITION) - *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()) << uint16(player->GetPositionZ()); + { + *data << uint16(player->GetPositionX()); + *data << uint16(player->GetPositionY()); + *data << uint16(player->GetPositionZ()); + } if (mask & GROUP_UPDATE_FLAG_AURAS) { @@ -1079,14 +1101,6 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint16(0); } - if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) - { - if (Vehicle* veh = player->GetVehicle()) - *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]); - else - *data << uint32(0); - } - if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) @@ -1136,6 +1150,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint32(0); // count // for (count) *data << uint16(phaseId) } + + if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) + { + if (Vehicle* veh = player->GetVehicle()) + *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]); + else + *data << uint32(0); + + } } /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ @@ -1151,35 +1174,68 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(guid); - data << (uint32) GROUP_UPDATE_FLAG_STATUS; - data << (uint16) MEMBER_STATUS_OFFLINE; + data << uint32(GROUP_UPDATE_FLAG_STATUS); + data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); + Powers powerType = player->getPowerType(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); - uint32 mask1 = GROUP_UPDATE_FULL; + uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP + | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL + | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS + | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS; - if (!pet) - mask1 &= ~GROUP_UPDATE_PET; + if (powerType != POWER_MANA) + updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE; - Powers powerType = player->getPowerType(); - data << uint32(mask1); // group update mask - data << uint16(MEMBER_STATUS_ONLINE); // member's online status, GROUP_UPDATE_FLAG_STATUS - data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP - data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP - data << uint8 (powerType); // GROUP_UPDATE_FLAG_POWER_TYPE - data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER - data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER - data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL - data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE - data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION - data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION + if (pet) + updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP + | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER; + + if (player->GetVehicle()) + updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; + + uint16 playerStatus = MEMBER_STATUS_ONLINE; + if (player->IsPvP()) + playerStatus |= MEMBER_STATUS_PVP; + + if (!player->isAlive()) + { + if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + playerStatus |= MEMBER_STATUS_GHOST; + else + playerStatus |= MEMBER_STATUS_DEAD; + } + + if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + playerStatus |= MEMBER_STATUS_PVP_FFA; + + if (player->isAFK()) + playerStatus |= MEMBER_STATUS_AFK; + + if (player->isDND()) + playerStatus |= MEMBER_STATUS_DND; + + data << uint32(updateFlags); + data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS + data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP + data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP + if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE) + data << uint8(powerType); + + data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER + data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER + data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL + data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE + data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION + data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION // GROUP_UPDATE_FLAG_AURAS @@ -1188,6 +1244,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder data << uint32(MAX_AURAS); // count + for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = player->GetVisibleAura(i)) @@ -1211,24 +1268,39 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS + if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID) + data << uint64(pet->GetGUID()); + + data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME + data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID + + if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP) + data << uint32(pet->GetHealth()); + + if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP) + data << uint32(pet->GetMaxHealth()); + + if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE) + data << (uint8)pet->getPowerType(); + + if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER) + data << uint16(pet->GetPower(pet->getPowerType())); + + if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER) + data << uint16(pet->GetMaxPower(pet->getPowerType())); + + uint64 petAuraMask = 0; + maskPos = data.wpos(); + data << uint64(petAuraMask); // placeholder if (pet) { - Powers petpowertype = pet->getPowerType(); - data << uint64(pet->GetGUID()); // GROUP_UPDATE_FLAG_PET_GUID - data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME - data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID - data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP - data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP - data << uint8 (petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE - data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER - data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER - // GROUP_UPDATE_FLAG_PET_AURAS data << uint8(1); uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder data << uint32(MAX_AURAS); // count + for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication const* aurApp = pet->GetVisibleAura(i)) @@ -1260,6 +1332,11 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) data << uint32(0); // count // for (count) *data << uint16(phaseId) + data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS + + if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) + data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]); + SendPacket(&data); } diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 45d4b0198e6..af7d853bfc6 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1451,7 +1451,7 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData) if (WorldObject* target = _player->GetViewpoint()) _player->SetSeer(target); else - sLog->outError(LOG_FILTER_NETWORKIO, "Player %s requests non-existing seer " UI64FMTD, _player->GetName().c_str(), _player->GetUInt64Value(PLAYER_FARSIGHT)); + sLog->outError(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) requests non-existing seer " UI64FMTD, _player->GetName().c_str(), GUID_LOPART(_player->GetGUID()), _player->GetUInt64Value(PLAYER_FARSIGHT)); } else { diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 892a926d2c3..1a2e825441f 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -65,19 +65,20 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->m_InstanceValid = true; Map* oldMap = GetPlayer()->GetMap(); + Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer()); + if (GetPlayer()->IsInWorld()) { - sLog->outError(LOG_FILTER_NETWORKIO, "Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName().c_str(), oldMap->GetId(), loc.GetMapId()); + sLog->outError(LOG_FILTER_NETWORKIO, "Player %s (GUID: %u) is still in world when teleported from map %s (%u) to new map %s (%u)", GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID()), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId()); oldMap->RemovePlayerFromMap(GetPlayer(), false); } // relocate the player to the teleport destination - Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer()); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (!newMap || !newMap->CanEnter(GetPlayer())) { - sLog->outError(LOG_FILTER_NETWORKIO, "Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); + sLog->outError(LOG_FILTER_NETWORKIO, "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); return; } @@ -90,8 +91,8 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->SendInitialPacketsBeforeAddToMap(); if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer())) { - sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", - GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); + sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: failed to teleport player %s (%d) to map %d (%s) because of unknown reason!", + GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown"); GetPlayer()->ResetMap(); GetPlayer()->SetMap(oldMap); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 76185dcd6cd..8e6fe56150a 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -79,13 +79,13 @@ void WorldSession::HandlePetAction(WorldPacket& recvData) if (!pet) { - sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetAction: Pet (GUID: %u) doesn't exist for player '%s'", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str()); + sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetAction: Pet (GUID: %u) doesn't exist for player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } if (pet != GetPlayer()->GetFirstControlled()) { - sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetAction: Pet (GUID: %u) does not belong to player '%s'", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str()); + sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetAction: Pet (GUID: %u) does not belong to player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } @@ -724,7 +724,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) { - sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName().c_str()); + sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s (GUID: %u).", uint32(GUID_LOPART(guid)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } @@ -769,7 +769,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) { - sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName().c_str()); + sLog->outError(LOG_FILTER_NETWORKIO, "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s (GUID: %u).", uint32(GUID_LOPART(guid)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index 2da2735a3f9..7b35462e7a2 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -41,10 +41,15 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) } GMTicketResponse response = GMTICKET_RESPONSE_CREATE_ERROR; + GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()); + + if (ticket && ticket->IsCompleted()) + sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());; + // Player must not have ticket - if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) + if (!ticket || ticket->IsClosed()) { - GmTicket* ticket = new GmTicket(GetPlayer(), recvData); + ticket = new GmTicket(GetPlayer(), recvData); uint32 count; std::list<uint32> times; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b73d6fd3c66..30316306882 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2421,7 +2421,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) // cannot enter other instances if bound permanently if (playerBind->save != mapSave) { - sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: player %s(%d) is permanently bound to instance %d, %d, %d, %d, %d, %d but he is being put into instance %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); + sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: player %s(%d) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); return false; } } @@ -2433,9 +2433,9 @@ bool InstanceMap::AddPlayerToMap(Player* player) InstanceGroupBind* groupBind = group->GetBoundInstance(this); if (playerBind && playerBind->save != mapSave) { - sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d, %d, %d, %d but he is in group %d and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(group->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %d and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(group->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); if (groupBind) - sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: the group is bound to the instance %d, %d, %d, %d, %d, %d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + sLog->outError(LOG_FILTER_MAPS, "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); //ASSERT(false); return false; } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index ca48fc8730d..62a0841405c 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -119,7 +119,10 @@ enum TrinityStrings LANG_RBAC_LIST_GROUPS_HEADER = 93, LANG_RBAC_LIST_ROLES_HEADER = 94, LANG_RBAC_LIST_PERMISSIONS_HEADER = 95, - // Room for more level 0 96-99 not used + LANG_GUILD_RENAME_ALREADY_EXISTS = 96, + LANG_GUILD_RENAME_DONE = 97, + LANG_RENAME_PLAYER_ALREADY_EXISTS = 98, + LANG_RENAME_PLAYER_WITH_NEW_NAME = 99, // level 1 chat LANG_GLOBAL_NOTIFY = 100, @@ -196,7 +199,7 @@ enum TrinityStrings LANG_COMMAND_TELE_NOTFOUND = 164, LANG_COMMAND_TELE_PARAMETER = 165, LANG_COMMAND_TELE_NOLOCATION = 166, - // 167 // not used + LANG_RESERVED_NAME = 167, LANG_COMMAND_TELE_LOCATION = 168, LANG_MAIL_SENT = 169, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 8e045b98dbb..a7148055376 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -426,7 +426,7 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, void MotionMaster::MoveCharge(PathGenerator const& path) { - Vector3 dest = path.GetActualEndPosition(); + G3D::Vector3 dest = path.GetActualEndPosition(); MoveCharge(dest.x, dest.y, dest.z, SPEED_CHARGE, EVENT_CHARGE_PREPATH); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 07e33f353c7..046f24e67b2 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -28,9 +28,10 @@ ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : - _polyLength(0), _type(PATHFIND_BLANK), - _useStraightPath(false), _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), - _endPosition(Vector3::zero()), _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL) + _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), + _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), + _endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL), + _navMeshQuery(NULL) { sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); @@ -58,10 +59,10 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; - Vector3 dest(destX, destY, destZ); + G3D::Vector3 dest(destX, destY, destZ); SetEndPosition(dest); - Vector3 start(x, y, z); + G3D::Vector3 start(x, y, z); SetStartPosition(start); _forceDestination = forceDest; @@ -151,7 +152,7 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) return INVALID_POLYREF; } -void PathGenerator::BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos) +void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos) { // *** getting start/end poly logic *** @@ -202,7 +203,7 @@ void PathGenerator::BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos { Creature* owner = (Creature*)_sourceUnit; - Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; + G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); @@ -230,7 +231,7 @@ void PathGenerator::BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos if (DT_SUCCESS == _navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); - SetActualEndPosition(Vector3(endPoint[2], endPoint[0], endPoint[1])); + SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); } _type = PATHFIND_INCOMPLETE; @@ -449,7 +450,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) - _pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); NormalizePath(); @@ -563,7 +564,7 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) } } -bool PathGenerator::HaveTile(const Vector3& p) const +bool PathGenerator::HaveTile(const G3D::Vector3& p) const { int tx = -1, ty = -1; float point[VERTEX_SIZE] = {p.y, p.z, p.x}; @@ -791,13 +792,13 @@ bool PathGenerator::InRangeYZX(const float* v1, const float* v2, float r, float return (dx * dx + dz * dz) < r * r && fabsf(dy) < h; } -bool PathGenerator::InRange(Vector3 const& p1, Vector3 const& p2, float r, float h) const +bool PathGenerator::InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const { - Vector3 d = p1 - p2; + G3D::Vector3 d = p1 - p2; return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h; } -float PathGenerator::Dist3DSqr(Vector3 const& p1, Vector3 const& p2) const +float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const { return (p1 - p2).squaredLength(); } diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index d41d3160db5..ac66b7cec57 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -24,9 +24,6 @@ #include "DetourNavMeshQuery.h" #include "MoveSplineInitArgs.h" -using Movement::Vector3; -using Movement::PointsArray; - class Unit; // 74*4.0f=296y number_of_points*interval = max_path_len @@ -63,42 +60,43 @@ class PathGenerator bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); // option setters - use optional - void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }; - void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; + void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; } + void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); } // result getters - Vector3 const& GetStartPosition() const { return _startPosition; } - Vector3 const& GetEndPosition() const { return _endPosition; } - Vector3 const& GetActualEndPosition() const { return _actualEndPosition; } + G3D::Vector3 const& GetStartPosition() const { return _startPosition; } + G3D::Vector3 const& GetEndPosition() const { return _endPosition; } + G3D::Vector3 const& GetActualEndPosition() const { return _actualEndPosition; } + + Movement::PointsArray const& GetPath() const { return _pathPoints; } - PointsArray const& GetPath() const { return _pathPoints; } PathType GetPathType() const { return _type; } private: - dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 _polyLength; // number of polygons in the path + dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references + uint32 _polyLength; // number of polygons in the path - PointsArray _pathPoints; // our actual (x,y,z) path to the target - PathType _type; // tells what kind of path this is + Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target + PathType _type; // tells what kind of path this is - bool _useStraightPath; // type of path will be generated - bool _forceDestination; // when set, we will always arrive at given point - uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) + bool _useStraightPath; // type of path will be generated + bool _forceDestination; // when set, we will always arrive at given point + uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) - Vector3 _startPosition; // {x, y, z} of current location - Vector3 _endPosition; // {x, y, z} of the destination - Vector3 _actualEndPosition;// {x, y, z} of the closest possible point to given destination + G3D::Vector3 _startPosition; // {x, y, z} of current location + G3D::Vector3 _endPosition; // {x, y, z} of the destination + G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination - Unit const* const _sourceUnit; // the unit that is moving - dtNavMesh const* _navMesh; // the nav mesh - dtNavMeshQuery const* _navMeshQuery; // the nav mesh query used to find the path + Unit const* const _sourceUnit; // the unit that is moving + dtNavMesh const* _navMesh; // the nav mesh + dtNavMeshQuery const* _navMeshQuery; // the nav mesh query used to find the path - dtQueryFilter _filter; // use single filter for all movements, update it when needed + dtQueryFilter _filter; // use single filter for all movements, update it when needed - void SetStartPosition(Vector3 Point) { _startPosition = Point; } - void SetEndPosition(Vector3 Point) { _actualEndPosition = Point; _endPosition = Point; } - void SetActualEndPosition(Vector3 Point) { _actualEndPosition = Point; } + void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; } + void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; } + void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; } void NormalizePath(); void Clear() @@ -107,15 +105,15 @@ class PathGenerator _pathPoints.clear(); } - bool InRange(Vector3 const& p1, Vector3 const& p2, float r, float h) const; - float Dist3DSqr(Vector3 const& p1, Vector3 const& p2) const; + bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const; + float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const; bool InRangeYZX(float const* v1, float const* v2, float r, float h) const; dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = NULL) const; dtPolyRef GetPolyByLocation(float const* Point, float* Distance) const; - bool HaveTile(Vector3 const& p) const; + bool HaveTile(G3D::Vector3 const& p) const; - void BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos); + void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos); void BuildPointPath(float const* startPoint, float const* endPoint); void BuildShortcut(); diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 93bf7edc7d5..684bc43ceaa 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -280,10 +280,17 @@ bool OPvPCapturePoint::Update(uint32 diff) float radius = (float)m_capturePoint->GetGOInfo()->capturePoint.radius; for (uint32 team = 0; team < 2; ++team) - for (PlayerSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) + { + for (PlayerSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end();) + { + uint64 playerGuid = *itr; + ++itr; + + if (Player* player = ObjectAccessor::FindPlayer(playerGuid)) if (!m_capturePoint->IsWithinDistInMap(player, radius) || !player->IsOutdoorPvPActive()) HandlePlayerLeave(player); + } + } std::list<Player*> players; Trinity::AnyPlayerInObjectRangeCheck checker(m_capturePoint, radius); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index d904e1365be..fbfd467e7eb 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -640,6 +640,7 @@ void AddScripts() AddKalimdorScripts(); AddOutlandScripts(); AddNorthrendScripts(); + AddEventScripts(); AddBattlegroundScripts(); AddOutdoorPvPScripts(); AddCustomScripts(); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 074e04547f6..ae4f983b154 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -861,12 +861,7 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data) SavedAddon const* savedAddon = AddonMgr::GetAddonInfo(addonName); if (savedAddon) { - bool match = true; - if (addon.CRC != savedAddon->CRC) - match = false; - - if (!match) sLog->outInfo(LOG_FILTER_GENERAL, "ADDON: %s was known, but didn't match known CRC (0x%x)!", addon.Name.c_str(), savedAddon->CRC); else sLog->outInfo(LOG_FILTER_GENERAL, "ADDON: %s was known, CRC is correct (0x%x)", addon.Name.c_str(), savedAddon->CRC); @@ -885,9 +880,6 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data) uint32 currentTime; addonInfo >> currentTime; sLog->outDebug(LOG_FILTER_NETWORKIO, "ADDON: CurrentTime: %u", currentTime); - - if (addonInfo.rpos() != addonInfo.size()) - sLog->outDebug(LOG_FILTER_NETWORKIO, "packet under-read!"); } else sLog->outError(LOG_FILTER_GENERAL, "Addon packet uncompress error!"); @@ -938,18 +930,23 @@ void WorldSession::SendAddonsInfo() data << uint32(0); /// @todo Find out the meaning of this. } - uint8 unk3 = 0; // 0 is sent here - data << uint8(unk3); - if (unk3) - { - // String, length 256 (null terminated) - data << uint8(0); - } + data << uint8(0); // uses URL + //if (usesURL) + // data << uint8(0); // URL } m_addonsList.clear(); - data << uint32(0); // count for an unknown for loop + AddonMgr::BannedAddonList const* bannedAddons = AddonMgr::GetBannedAddons(); + data << uint32(bannedAddons->size()); + for (AddonMgr::BannedAddonList::const_iterator itr = bannedAddons->begin(); itr != bannedAddons->end(); ++itr) + { + data << uint32(itr->Id); + data.append(itr->NameMD5, sizeof(itr->NameMD5)); + data.append(itr->VersionMD5, sizeof(itr->VersionMD5)); + data << uint32(itr->Timestamp); + data << uint32(1); // IsBanned + } SendPacket(&data); } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f75adc19258..9882b16dcd2 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2990,12 +2990,10 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m return; Unit* target = aurApp->GetTarget(); - if (!target->IsVehicle()) return; Unit* caster = GetCaster(); - if (!caster || caster == target) return; @@ -5840,8 +5838,8 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? caster : target) { - int32 basepoints0 = GetAmount(); - triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints0, 0, 0, true, 0, this); + int32 basepoints = GetAmount(); + triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, 0, this); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); } } diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 99fbd8fbe03..b22f1ef0837 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1524,7 +1524,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const return true; // Dynobj auras always stack - if (existingAura->GetType() == DYNOBJ_AURA_TYPE) + if (GetType() == DYNOBJ_AURA_TYPE || existingAura->GetType() == DYNOBJ_AURA_TYPE) return true; SpellInfo const* existingSpellInfo = existingAura->GetSpellInfo(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ced288d8fa7..f61ac6f8f35 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1374,7 +1374,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); return; case TARGET_DEST_DB: - if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id)) + if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex)) { /// @todo fix this check if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND)) @@ -7405,7 +7405,7 @@ WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Po bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target) { - if (!target->IsWithinDist3d(_position, _range)) + if (!target->IsWithinDist3d(_position, _range) && !(target->ToGameObject() && target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range))) return false; return WorldObjectSpellTargetCheck::operator ()(target); } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 0266b98ecfb..015e90da34d 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -811,7 +811,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) // set basepoints for trigger with value effect if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) { - // maybe need to set value only when basepoints == 0? values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage); @@ -1826,7 +1825,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) return; case GAMEOBJECT_TYPE_QUESTGIVER: - player->PrepareGossipMenu(gameObjTarget, gameObjTarget->GetGOInfo()->questgiver.gossipID); + player->PrepareGossipMenu(gameObjTarget, gameObjTarget->GetGOInfo()->questgiver.gossipID, true); player->SendPreparedGossip(gameObjTarget); return; @@ -2239,8 +2238,6 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) case SUMMON_CATEGORY_VEHICLE: // Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker // to cast a ride vehicle spell on the summoned unit. - float x, y, z; - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); summon = m_originalCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_caster, m_spellInfo->Id); if (!summon || !summon->IsVehicle()) return; @@ -3087,7 +3084,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Blood-Caked Strike - Blood-Caked Blade if (m_spellInfo->SpellIconID == 1736) { - AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 12.5f); + AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 50.0f); break; } // Heart Strike @@ -5837,7 +5834,7 @@ void Spell::EffectBind(SpellEffIndex effIndex) player->SetHomebind(homeLoc, areaId); // binding - WorldPacket data(SMSG_BINDPOINTUPDATE, (4+4+4+4+4)); + WorldPacket data(SMSG_BINDPOINTUPDATE, 4 + 4 + 4 + 4 + 4); data << float(homeLoc.GetPositionX()); data << float(homeLoc.GetPositionY()); data << float(homeLoc.GetPositionZ()); @@ -5849,8 +5846,8 @@ void Spell::EffectBind(SpellEffIndex effIndex) homeLoc.GetPositionX(), homeLoc.GetPositionY(), homeLoc.GetPositionZ(), homeLoc.GetMapId(), areaId); // zone update - data.Initialize(SMSG_PLAYERBOUND, 8+4); - data << uint64(player->GetGUID()); + data.Initialize(SMSG_PLAYERBOUND, 8 + 4); + data << uint64(m_caster->GetGUID()); data << uint32(areaId); player->SendDirectMessage(&data); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 7a9ef241ad3..b381249cdcc 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -508,6 +508,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value); // amount multiplication based on caster's level +/* REVIEW - MERGE <<<<<<< HEAD if (!_spellInfo->GetSpellScaling() && !basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) && Effect != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE && Effect != SPELL_EFFECT_KNOCK_BACK && @@ -519,6 +520,58 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const //there are many more: slow speed, -healing pct value *= 0.25f * exp(caster->getLevel() * (70 - _spellInfo->SpellLevel) / 1000.0f); //value = int32(value * (int32)getLevel() / (int32)(_spellInfo->spellLevel ? _spellInfo->spellLevel : 1)); +======= */ + if (!caster->IsControlledByPlayer() && + _spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() && + !basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION)) + { + bool canEffectScale = false; + switch (Effect) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_DUMMY: + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_SCRIPT_EFFECT: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_FORCE_CAST_WITH_VALUE: + case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: + case SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE: + canEffectScale = true; + break; + default: + break; + } + + switch (ApplyAuraName) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_DUMMY: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_DAMAGE_SHIELD: + case SPELL_AURA_PROC_TRIGGER_DAMAGE: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_SCHOOL_ABSORB: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + canEffectScale = true; + break; + default: + break; + } + + if (canEffectScale) + { + GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(_spellInfo->SpellLevel - 1); + GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1); + if (spellScaler && casterScaler) + value *= casterScaler->ratio / spellScaler->ratio; + } + } +// REVIEW - MERGE >>>>>>> master } return int32(value); @@ -2313,15 +2366,41 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c continue; powerCost += (*i)->GetAmount(); } + // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) if (AttributesEx4 & SPELL_ATTR4_SPELL_VS_EXTEND_COST) - powerCost += caster->GetAttackTime(OFF_ATTACK) / 100; + { + uint32 speed = 0; +/* REVIEW - MERGE + if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm())) + speed = ss->attackSpeed; + else +*/ + { + WeaponAttackType slot = BASE_ATTACK; + if (AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND) + slot = OFF_ATTACK; + + speed = caster->GetAttackTime(slot); + } + + powerCost += speed / 100; + } + // Apply cost mod by spell if (Player* modOwner = caster->GetSpellModOwner()) modOwner->ApplySpellMod(Id, SPELLMOD_COST, powerCost); - if (Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION) - powerCost = int32(powerCost / (1.117f * SpellLevel / caster->getLevel() -0.1327f)); + if (!caster->IsControlledByPlayer()) + { + if (Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION) + { + GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(SpellLevel - 1); + GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1); + if (spellScaler && casterScaler) + powerCost *= casterScaler->ratio / spellScaler->ratio; + } + } // PCT mod from user auras by spell school and power type Unit::AuraEffectList const& aurasPct = caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT); @@ -2611,7 +2690,7 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const continue; // if non-positive trigger cast targeted to positive target this main cast is non-positive // this will place this spell auras as debuffs - if (_IsPositiveTarget(spellTriggeredProto->Effects[i].TargetA.GetTarget(), spellTriggeredProto->Effects[i].TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(i, true)) + if (!_IsPositiveTarget(spellTriggeredProto->Effects[i].TargetA.GetTarget(), spellTriggeredProto->Effects[i].TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(i, true)) return false; } } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 9ae8e7ec8f7..7da054b4f7a 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -620,9 +620,9 @@ bool SpellMgr::IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const return false; } -SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id) const +SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const { - SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find(spell_id); + SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find(std::make_pair(spell_id, effIndex)); if (itr != mSpellTargetPositions.end()) return &itr->second; return NULL; @@ -1554,8 +1554,8 @@ void SpellMgr::LoadSpellTargetPositions() mSpellTargetPositions.clear(); // need for reload case - // 0 1 2 3 4 5 - QueryResult result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position"); + // 0 1 2 3 4 5 6 + QueryResult result = WorldDatabase.Query("SELECT id, effIndex, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty."); @@ -1568,25 +1568,26 @@ void SpellMgr::LoadSpellTargetPositions() Field* fields = result->Fetch(); uint32 Spell_ID = fields[0].GetUInt32(); + SpellEffIndex effIndex = SpellEffIndex(fields[1].GetUInt8()); SpellTargetPosition st; - st.target_mapId = fields[1].GetUInt16(); - st.target_X = fields[2].GetFloat(); - st.target_Y = fields[3].GetFloat(); - st.target_Z = fields[4].GetFloat(); - st.target_Orientation = fields[5].GetFloat(); + st.target_mapId = fields[2].GetUInt16(); + st.target_X = fields[3].GetFloat(); + st.target_Y = fields[4].GetFloat(); + st.target_Z = fields[5].GetFloat(); + st.target_Orientation = fields[6].GetFloat(); MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId); if (!mapEntry) { - sLog->outError(LOG_FILTER_SQL, "Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.", Spell_ID, st.target_mapId); + sLog->outError(LOG_FILTER_SQL, "Spell (Id: %u, effIndex: %u) target map (ID: %u) does not exist in `Map.dbc`.", Spell_ID, effIndex, st.target_mapId); continue; } if (st.target_X==0 && st.target_Y==0 && st.target_Z==0) { - sLog->outError(LOG_FILTER_SQL, "Spell (ID:%u) target coordinates not provided.", Spell_ID); + sLog->outError(LOG_FILTER_SQL, "Spell (Id: %u, effIndex: %u) target coordinates not provided.", Spell_ID, effIndex); continue; } @@ -1597,35 +1598,18 @@ void SpellMgr::LoadSpellTargetPositions() continue; } - bool found = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_DEST_DB || spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DB) { - if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DB || spellInfo->Effects[i].TargetB.GetTarget() == TARGET_DEST_DB) - { - // additional requirements - if (spellInfo->Effects[i].Effect == SPELL_EFFECT_BIND && spellInfo->Effects[i].MiscValue) - { - uint32 area_id = sMapMgr->GetAreaId(st.target_mapId, st.target_X, st.target_Y, st.target_Z); - if (area_id != uint32(spellInfo->Effects[i].MiscValue)) - { - sLog->outError(LOG_FILTER_SQL, "Spell (Id: %u) listed in `spell_target_position` expected point to zone %u bit point to zone %u.", Spell_ID, spellInfo->Effects[i].MiscValue, area_id); - break; - } - } - - found = true; - break; - } + std::pair<uint32, SpellEffIndex> key = std::make_pair(Spell_ID, effIndex); + mSpellTargetPositions[key] = st; + ++count; } - if (!found) + else { - sLog->outError(LOG_FILTER_SQL, "Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_DEST_DB (17).", Spell_ID); + sLog->outError(LOG_FILTER_SQL, "Spell (Id: %u, effIndex: %u) listed in `spell_target_position` does not have target TARGET_DEST_DB (17).", Spell_ID, effIndex); continue; } - mSpellTargetPositions[Spell_ID] = st; - ++count; - } while (result->NextRow()); /* diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index d63aa679381..69eedf25186 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -377,6 +377,8 @@ struct SpellTargetPosition float target_Orientation; }; +typedef std::map<std::pair<uint32 /*spell_id*/, SpellEffIndex /*effIndex*/>, SpellTargetPosition> SpellTargetPositionMap; + // Enum with EffectRadiusIndex and their actual radius enum EffectRadiusIndex { @@ -439,8 +441,6 @@ enum EffectRadiusIndex EFFECT_RADIUS_80_YARDS_2 = 65 }; -typedef UNORDERED_MAP<uint32, SpellTargetPosition> SpellTargetPositionMap; - // Spell pet auras class PetAura { @@ -643,7 +643,7 @@ class SpellMgr bool IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const; // Spell target coordinates - SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const; + SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const; // Spell Groups table SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const; diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index 55b4d3f2e22..373f123b6a0 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -244,7 +244,10 @@ void GmTicket::SetChatLog(std::list<uint32> time, std::string const& log) /////////////////////////////////////////////////////////////////////////////////////////////////// // Ticket manager -TicketMgr::TicketMgr() : _status(true), _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)) { } +TicketMgr::TicketMgr() : _status(true), _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), + _lastChange(time(NULL)) +{ +} TicketMgr::~TicketMgr() { @@ -252,7 +255,10 @@ TicketMgr::~TicketMgr() delete itr->second; } -void TicketMgr::Initialize() { SetStatus(sWorld->getBoolConfig(CONFIG_ALLOW_TICKETS)); } +void TicketMgr::Initialize() +{ + SetStatus(sWorld->getBoolConfig(CONFIG_ALLOW_TICKETS)); +} void TicketMgr::ResetTickets() { diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index 0fe45f81360..91ef98dda23 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -82,7 +82,7 @@ class GmTicket { public: GmTicket(); - explicit GmTicket(Player* player, WorldPacket& recvData); + GmTicket(Player* player, WorldPacket& recvData); ~GmTicket(); bool IsClosed() const { return _closedBy; } @@ -119,7 +119,8 @@ public: else if (_escalatedStatus == TICKET_UNASSIGNED) _escalatedStatus = TICKET_ASSIGNED; } - void SetClosedBy(const int64& value) { _closedBy = value; } + void SetClosedBy(int64 value) { _closedBy = value; } + void SetCompleted() { _completed = true; } void SetMessage(std::string const& message) { _message = message; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 71439254647..164ce463d65 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1135,6 +1135,7 @@ void World::LoadConfigSettings(bool reload) ///- Load the CharDelete related config options m_int_configs[CONFIG_CHARDELETE_METHOD] = ConfigMgr::GetIntDefault("CharDelete.Method", 0); m_int_configs[CONFIG_CHARDELETE_MIN_LEVEL] = ConfigMgr::GetIntDefault("CharDelete.MinLevel", 0); + m_int_configs[CONFIG_CHARDELETE_HEROIC_MIN_LEVEL] = ConfigMgr::GetIntDefault("CharDelete.Heroic.MinLevel", 0); m_int_configs[CONFIG_CHARDELETE_KEEP_DAYS] = ConfigMgr::GetIntDefault("CharDelete.KeepDays", 30); ///- Read the "Data" directory from the config file @@ -1837,7 +1838,7 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Calculate random battleground reset time..."); InitRandomBGResetTime(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Calculate Guild cap reset time..."); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Calculate guild limitation(s) reset time..."); InitGuildResetTime(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Calculate next currency reset time..."); @@ -1893,12 +1894,16 @@ void World::LoadAutobroadcasts() uint32 oldMSTime = getMSTime(); m_Autobroadcasts.clear(); + m_AutobroadcastsWeights.clear(); - QueryResult result = WorldDatabase.Query("SELECT text FROM autobroadcast"); + uint32 realmId = ConfigMgr::GetIntDefault("RealmID", 0); + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_AUTOBROADCAST); + stmt->setInt32(0, realmId); + PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty!"); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty for this realm!"); return; } @@ -1907,9 +1912,10 @@ void World::LoadAutobroadcasts() do { Field* fields = result->Fetch(); - std::string message = fields[0].GetString(); + uint8 id = fields[0].GetUInt8(); - m_Autobroadcasts.push_back(message); + m_Autobroadcasts[id] = fields[2].GetString(); + m_AutobroadcastsWeights[id] = fields[1].GetUInt8(); ++count; } while (result->NextRow()); @@ -2671,9 +2677,35 @@ void World::SendAutoBroadcast() if (m_Autobroadcasts.empty()) return; + uint32 weight = 0; + AutobroadcastsWeightMap selectionWeights; std::string msg; - msg = Trinity::Containers::SelectRandomContainerElement(m_Autobroadcasts); + for (AutobroadcastsWeightMap::const_iterator it = m_AutobroadcastsWeights.begin(); it != m_AutobroadcastsWeights.end(); ++it) + { + if (it->second) + { + weight += it->second; + selectionWeights[it->first] = it->second; + } + } + + if (weight) + { + uint32 selectedWeight = urand(0, weight - 1); + weight = 0; + for (AutobroadcastsWeightMap::const_iterator it = selectionWeights.begin(); it != selectionWeights.end(); ++it) + { + weight += it->second; + if (selectedWeight < weight) + { + msg = m_Autobroadcasts[it->first]; + break; + } + } + } + else + msg = m_Autobroadcasts[urand(0, m_Autobroadcasts.size())]; uint32 abcenter = sWorld->getIntConfig(CONFIG_AUTOBROADCAST_CENTER); @@ -3129,6 +3161,27 @@ void World::ProcessQueryCallbacks() } } +/** +* @brief Loads several pieces of information on server startup with the low GUID +* There is no further database query necessary. +* These are a number of methods that work into the calling function. +* +* @param guid Requires a lowGUID to call +* @return Name, Gender, Race, Class and Level of player character +* Example Usage: +* @code +* CharacterNameData const* nameData = sWorld->GetCharacterNameData(lowGUID); +* if (!nameData) +* return; +* +* std::string playerName = nameData->m_name; +* uint8 playerGender = nameData->m_gender; +* uint8 playerRace = nameData->m_race; +* uint8 playerClass = nameData->m_class; +* uint8 playerLevel = nameData->m_level; +* @endcode +**/ + void World::LoadCharacterNameData() { sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading character name data"); @@ -3206,7 +3259,7 @@ void World::UpdatePhaseDefinitions() void World::ReloadRBAC() { - // Pasive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded + // Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded sLog->outInfo(LOG_FILTER_RBAC, "World::ReloadRBAC()"); for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) if (WorldSession* session = itr->second) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 1aa93ce5486..ca76bef435d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -312,6 +312,7 @@ enum WorldIntConfigs CONFIG_CHARDELETE_KEEP_DAYS, CONFIG_CHARDELETE_METHOD, CONFIG_CHARDELETE_MIN_LEVEL, + CONFIG_CHARDELETE_HEROIC_MIN_LEVEL, CONFIG_AUTOBROADCAST_CENTER, CONFIG_AUTOBROADCAST_INTERVAL, CONFIG_MAX_RESULTS_LOOKUP_COMMANDS, @@ -843,7 +844,11 @@ class World // used versions std::string m_DBVersion; - std::list<std::string> m_Autobroadcasts; + typedef std::map<uint8, std::string> AutobroadcastsMap; + AutobroadcastsMap m_Autobroadcasts; + + typedef std::map<uint8, uint8> AutobroadcastsWeightMap; + AutobroadcastsWeightMap m_AutobroadcastsWeights; std::map<uint32, CharacterNameData> _characterNameDataMap; void LoadCharacterNameData(); diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 3953beab3da..cf2816c985e 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -42,13 +42,19 @@ public: { "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "", NULL }, { NULL, SEC_PLAYER, false, NULL, "", NULL } }; + static ChatCommand accountLockCommandTable[] = + { + { "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "", NULL }, + { "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "", NULL }, + { NULL, SEC_PLAYER, false, NULL, "", NULL }, + }; static ChatCommand accountCommandTable[] = { { "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "", NULL }, { "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "", NULL }, { "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "", NULL }, { "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "", NULL }, - { "lock", SEC_PLAYER, false, &HandleAccountLockCommand, "", NULL }, + { "lock", SEC_PLAYER, false, NULL, "", accountLockCommandTable }, { "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable }, { "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "", NULL }, { "", SEC_PLAYER, false, &HandleAccountCommand, "", NULL }, @@ -245,7 +251,57 @@ public: return true; } - static bool HandleAccountLockCommand(ChatHandler* handler, char const* args) + static bool HandleAccountLockCountryCommand(ChatHandler* handler, char const* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + return false; + } + std::string param = (char*)args; + + if (!param.empty()) + { + if (param == "on") + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); + uint32 ip = inet_addr(handler->GetSession()->GetRemoteAddress().c_str()); + EndianConvertReverse(ip); + stmt->setUInt32(0, ip); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (result) + { + Field* fields = result->Fetch(); + std::string country = fields[0].GetString(); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY); + stmt->setString(0, country); + stmt->setUInt32(1, handler->GetSession()->GetAccountId()); + LoginDatabase.Execute(stmt); + handler->PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); + } + else + { + handler->PSendSysMessage("[IP2NATION] Table empty"); + sLog->outDebug(LOG_FILTER_AUTHSERVER, "[IP2NATION] Table empty"); + } + } + else if (param == "off") + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY); + stmt->setString(0, "00"); + stmt->setUInt32(1, handler->GetSession()->GetAccountId()); + LoginDatabase.Execute(stmt); + handler->PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); + } + return true; + } + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + return false; + } + + static bool HandleAccountLockIpCommand(ChatHandler* handler, char const* args) { if (!*args) { diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 1ed00f32b87..727aa55597f 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -308,28 +308,121 @@ public: if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; - if (target) + char const* newNameStr = strtok(NULL, " "); + + if (newNameStr) { - // check online security - if (handler->HasLowerSecurity(target, 0)) + std::string playerOldName; + std::string newName = newNameStr; + + if (target) + { + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; + + playerOldName = target->GetName(); + } + else + { + // check offline security + if (handler->HasLowerSecurity(NULL, targetGuid)) + return false; + + sObjectMgr->GetPlayerNameByGUID(targetGuid, playerOldName); + } + + if (!normalizePlayerName(newName)) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + if (ObjectMgr::CheckPlayerName(newName, true) != CHAR_NAME_SUCCESS) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + if (WorldSession* session = handler->GetSession()) + { + if (!session->HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName)) + { + handler->SendSysMessage(LANG_RESERVED_NAME); + handler->SetSentErrorMessage(true); + return false; + } + } + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); + stmt->setString(0, newName); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (result) + { + handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str()); + handler->SetSentErrorMessage(true); return false; + } + + // Remove declined name from db + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME); + stmt->setUInt32(0, targetGuid); + CharacterDatabase.Execute(stmt); + + if (target) + { + target->SetName(newName); + + if (WorldSession* session = target->GetSession()) + session->KickPlayer(); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID); + stmt->setString(0, newName); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + } + + sWorld->UpdateCharacterNameData(targetGuid, newName); - handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_RENAME); + handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); + + if (WorldSession* session = handler->GetSession()) + { + if (Player* player = session->GetPlayer()) + sLog->outCommand(session->GetAccountId(), "GM %s (Account: %u) forced rename %s to player %s (Account: %u)", player->GetName().c_str(), session->GetAccountId(), newName.c_str(), playerOldName.c_str(), sObjectMgr->GetPlayerAccountIdByGUID(targetGuid)); + } + else + sLog->outCommand(0, "CONSOLE forced rename '%s' to '%s' (GUID: %u)", playerOldName.c_str(), newName.c_str(), GUID_LOPART(targetGuid)); } else { - // check offline security - if (handler->HasLowerSecurity(NULL, targetGuid)) - return false; + if (target) + { + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; - std::string oldNameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + } + else + { + // check offline security + if (handler->HasLowerSecurity(NULL, targetGuid)) + return false; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - CharacterDatabase.Execute(stmt); + std::string oldNameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + } } return true; diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 3bdd0fbe132..414f673463f 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -592,7 +592,8 @@ public: entry = object->GetEntry(); else entry = atoi((char*)args); - } + } else + entry = atoi((char*)args); GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate(entry); diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index 05f4e2bde67..ffaf1360ad5 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -44,6 +44,7 @@ public: { "invite", SEC_GAMEMASTER, true, &HandleGuildInviteCommand, "", NULL }, { "uninvite", SEC_GAMEMASTER, true, &HandleGuildUninviteCommand, "", NULL }, { "rank", SEC_GAMEMASTER, true, &HandleGuildRankCommand, "", NULL }, + { "rename", SEC_GAMEMASTER, true, &HandleGuildRenameCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = @@ -193,6 +194,55 @@ public: uint8 newRank = uint8(atoi(rankStr)); return targetGuild->ChangeMemberRank(targetGuid, newRank); } + + static bool HandleGuildRenameCommand(ChatHandler* handler, char const* _args) + { + if (!*_args) + return false; + + char *args = (char *)_args; + + char const* oldGuildStr = handler->extractQuotedArg(args); + if (!oldGuildStr) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + char const* newGuildStr = handler->extractQuotedArg(strtok(NULL, "")); + if (!newGuildStr) + { + handler->SendSysMessage(LANG_INSERT_GUILD_NAME); + handler->SetSentErrorMessage(true); + return false; + } + + Guild* guild = sGuildMgr->GetGuildByName(oldGuildStr); + if (!guild) + { + handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, oldGuildStr); + handler->SetSentErrorMessage(true); + return false; + } + + if (sGuildMgr->GetGuildByName(newGuildStr)) + { + handler->PSendSysMessage(LANG_GUILD_RENAME_ALREADY_EXISTS, newGuildStr); + handler->SetSentErrorMessage(true); + return false; + } + + if (!guild->SetName(newGuildStr)) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage(LANG_GUILD_RENAME_DONE, oldGuildStr, newGuildStr); + return true; + } }; void AddSC_guild_commandscript() diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 8357b0ec090..a953fe56e7e 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1586,13 +1586,9 @@ public: EndianConvertReverse(ip); #endif - PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_IP2NATION_COUNTRY); - + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY); stmt->setUInt32(0, ip); - - PreparedQueryResult result2 = WorldDatabase.Query(stmt); - - if (result2) + if (PreparedQueryResult result2 = LoginDatabase.Query(stmt)) { Field* fields2 = result2->Fetch(); lastIp.append(" ("); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 79cd0deb75e..55b6edbadbe 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -95,14 +95,14 @@ public: path.SetUseStraightPath(useStraightPath); bool result = path.CalculatePath(x, y, z); - PointsArray const& pointPath = path.GetPath(); + Movement::PointsArray const& pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); - handler->PSendSysMessage("Result: %s - Length: "SIZEFMTD" - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); + handler->PSendSysMessage("Result: %s - Length: " SIZEFMTD " - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); - Vector3 start = path.GetStartPosition(); - Vector3 end = path.GetEndPosition(); - Vector3 actualEnd = path.GetActualEndPosition(); + G3D::Vector3 const &start = path.GetStartPosition(); + G3D::Vector3 const &end = path.GetEndPosition(); + G3D::Vector3 const &actualEnd = path.GetActualEndPosition(); handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); @@ -264,7 +264,7 @@ public: if (!creatureList.empty()) { - handler->PSendSysMessage("Found "SIZEFMTD" Creatures.", creatureList.size()); + handler->PSendSysMessage("Found " SIZEFMTD " Creatures.", creatureList.size()); uint32 paths = 0; uint32 uStartTime = getMSTime(); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 95cbf70e1f8..0795b2ab90c 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -235,6 +235,10 @@ public: if (player->IsInWorld()) ticket->SendResponse(player->GetSession()); + SQLTransaction trans = SQLTransaction(NULL); + ticket->SetCompleted(); + ticket->SaveToDB(trans); + sTicketMgr->UpdateLastChange(); return true; } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index e4929eed313..020cdca8566 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -371,7 +371,7 @@ public: creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - sCreatureTextMgr->SendChat(creature, SAY_EVENT_ATTACK, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + sCreatureTextMgr->SendChat(creature, SAY_DUEL, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); player->CastSpell(creature, SPELL_DUEL, false); player->CastSpell(player, SPELL_DUEL_FLAG, true); @@ -861,59 +861,82 @@ public: ## npc_scarlet_miner_cart ####*/ -enum Spells_SM +enum ScarletMinerCart { - SPELL_CART_CHECK = 54173, - SPELL_CART_DRAG = 52465 + SPELL_CART_CHECK = 54173, + SPELL_SUMMON_CART = 52463, + SPELL_SUMMON_MINER = 52464, + SPELL_CART_DRAG = 52465, + + NPC_MINER = 28841 }; class npc_scarlet_miner_cart : public CreatureScript { -public: - npc_scarlet_miner_cart() : CreatureScript("npc_scarlet_miner_cart") { } + public: + npc_scarlet_miner_cart() : CreatureScript("npc_scarlet_miner_cart") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_scarlet_miner_cartAI(creature); - } - - struct npc_scarlet_miner_cartAI : public PassiveAI - { - npc_scarlet_miner_cartAI(Creature* creature) : PassiveAI(creature), minerGUID(0) + struct npc_scarlet_miner_cartAI : public PassiveAI { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse. - } + npc_scarlet_miner_cartAI(Creature* creature) : PassiveAI(creature), _minerGUID(0), _playerGUID(0) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse. + } - uint64 minerGUID; + void JustSummoned(Creature* summon) + { + if (summon->GetEntry() == NPC_MINER) + { + _minerGUID = summon->GetGUID(); + summon->AI()->SetGUID(_playerGUID); + } + } - void SetGUID(uint64 guid, int32 /*id*/) - { - minerGUID = guid; - } + void SummonedCreatureDespawn(Creature* summon) + { + if (summon->GetEntry() == NPC_MINER) + _minerGUID = 0; + } - void DoAction(int32 /*param*/) - { - if (Creature* miner = Unit::GetCreature(*me, minerGUID)) + void DoAction(int32 /*param*/) { - me->SetWalk(false); + if (Creature* miner = ObjectAccessor::GetCreature(*me, _minerGUID)) + { + me->SetWalk(false); - //Not 100% correct, but movement is smooth. Sometimes miner walks faster - //than normal, this speed is fast enough to keep up at those times. - me->SetSpeed(MOVE_RUN, 1.25f); + // Not 100% correct, but movement is smooth. Sometimes miner walks faster + // than normal, this speed is fast enough to keep up at those times. + me->SetSpeed(MOVE_RUN, 1.25f); - me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); + me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); + } } - } - void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) + { + if (apply) + { + _playerGUID = who->GetGUID(); + me->CastSpell((Unit*)NULL, SPELL_SUMMON_MINER, true); + } + else + { + _playerGUID = 0; + if (Creature* miner = ObjectAccessor::GetCreature(*me, _minerGUID)) + miner->DespawnOrUnsummon(); + } + } + + private: + uint64 _minerGUID; + uint64 _playerGUID; + }; + + CreatureAI* GetAI(Creature* creature) const { - if (!apply) - if (Creature* miner = Unit::GetCreature(*me, minerGUID)) - miner->DisappearAndDie(); + return new npc_scarlet_miner_cartAI(creature); } - }; - }; /*#### @@ -928,162 +951,130 @@ enum Says_SM class npc_scarlet_miner : public CreatureScript { -public: - npc_scarlet_miner() : CreatureScript("npc_scarlet_miner") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_scarlet_minerAI(creature); - } + public: + npc_scarlet_miner() : CreatureScript("npc_scarlet_miner") { } - struct npc_scarlet_minerAI : public npc_escortAI - { - npc_scarlet_minerAI(Creature* creature) : npc_escortAI(creature) + struct npc_scarlet_minerAI : public npc_escortAI { - me->SetReactState(REACT_PASSIVE); - } + npc_scarlet_minerAI(Creature* creature) : npc_escortAI(creature) + { + me->SetReactState(REACT_PASSIVE); + } - uint32 IntroTimer; - uint32 IntroPhase; - uint64 carGUID; + uint32 IntroTimer; + uint32 IntroPhase; + uint64 carGUID; - void Reset() - { - carGUID = 0; - IntroTimer = 0; - IntroPhase = 0; - } + void Reset() + { + carGUID = 0; + IntroTimer = 0; + IntroPhase = 0; + } - void InitWaypoint() - { - AddWaypoint(1, 2389.03f, -5902.74f, 109.014f, 5000); - AddWaypoint(2, 2341.812012f, -5900.484863f, 102.619743f); - AddWaypoint(3, 2306.561279f, -5901.738281f, 91.792419f); - AddWaypoint(4, 2300.098389f, -5912.618652f, 86.014885f); - AddWaypoint(5, 2294.142090f, -5927.274414f, 75.316849f); - AddWaypoint(6, 2286.984375f, -5944.955566f, 63.714966f); - AddWaypoint(7, 2280.001709f, -5961.186035f, 54.228283f); - AddWaypoint(8, 2259.389648f, -5974.197754f, 42.359348f); - AddWaypoint(9, 2242.882812f, -5984.642578f, 32.827850f); - AddWaypoint(10, 2217.265625f, -6028.959473f, 7.675705f); - AddWaypoint(11, 2202.595947f, -6061.325684f, 5.882018f); - AddWaypoint(12, 2188.974609f, -6080.866699f, 3.370027f); - - if (urand(0, 1)) + void IsSummonedBy(Unit* summoner) { - AddWaypoint(13, 2176.483887f, -6110.407227f, 1.855181f); - AddWaypoint(14, 2172.516602f, -6146.752441f, 1.074235f); - AddWaypoint(15, 2138.918457f, -6158.920898f, 1.342926f); - AddWaypoint(16, 2129.866699f, -6174.107910f, 4.380779f); - AddWaypoint(17, 2117.709473f, -6193.830078f, 13.3542f, 10000); + carGUID = summoner->GetGUID(); } - else + + void InitWaypoint() { - AddWaypoint(13, 2184.190186f, -6166.447266f, 0.968877f); - AddWaypoint(14, 2234.265625f, -6163.741211f, 0.916021f); - AddWaypoint(15, 2268.071777f, -6158.750977f, 1.822252f); - AddWaypoint(16, 2270.028320f, -6176.505859f, 6.340538f); - AddWaypoint(17, 2271.739014f, -6195.401855f, 13.3542f, 10000); + AddWaypoint(1, 2389.03f, -5902.74f, 109.014f, 5000); + AddWaypoint(2, 2341.812012f, -5900.484863f, 102.619743f); + AddWaypoint(3, 2306.561279f, -5901.738281f, 91.792419f); + AddWaypoint(4, 2300.098389f, -5912.618652f, 86.014885f); + AddWaypoint(5, 2294.142090f, -5927.274414f, 75.316849f); + AddWaypoint(6, 2286.984375f, -5944.955566f, 63.714966f); + AddWaypoint(7, 2280.001709f, -5961.186035f, 54.228283f); + AddWaypoint(8, 2259.389648f, -5974.197754f, 42.359348f); + AddWaypoint(9, 2242.882812f, -5984.642578f, 32.827850f); + AddWaypoint(10, 2217.265625f, -6028.959473f, 7.675705f); + AddWaypoint(11, 2202.595947f, -6061.325684f, 5.882018f); + AddWaypoint(12, 2188.974609f, -6080.866699f, 3.370027f); + + if (urand(0, 1)) + { + AddWaypoint(13, 2176.483887f, -6110.407227f, 1.855181f); + AddWaypoint(14, 2172.516602f, -6146.752441f, 1.074235f); + AddWaypoint(15, 2138.918457f, -6158.920898f, 1.342926f); + AddWaypoint(16, 2129.866699f, -6174.107910f, 4.380779f); + AddWaypoint(17, 2117.709473f, -6193.830078f, 13.3542f, 10000); + } + else + { + AddWaypoint(13, 2184.190186f, -6166.447266f, 0.968877f); + AddWaypoint(14, 2234.265625f, -6163.741211f, 0.916021f); + AddWaypoint(15, 2268.071777f, -6158.750977f, 1.822252f); + AddWaypoint(16, 2270.028320f, -6176.505859f, 6.340538f); + AddWaypoint(17, 2271.739014f, -6195.401855f, 13.3542f, 10000); + } } - } - void InitCartQuest(Player* who) - { - carGUID = who->GetVehicleBase()->GetGUID(); - InitWaypoint(); - Start(false, false, who->GetGUID()); - SetDespawnAtFar(false); - } + void SetGUID(uint64 guid, int32 /*id = 0*/) + { + InitWaypoint(); + Start(false, false, guid); + SetDespawnAtFar(false); + } - void WaypointReached(uint32 waypointId) - { - switch (waypointId) + void WaypointReached(uint32 waypointId) { - case 1: - if (Unit* car = Unit::GetCreature(*me, carGUID)) - me->SetFacingToObject(car); - Talk(SAY_SCARLET_MINER_0); - SetRun(true); - IntroTimer = 4000; - IntroPhase = 1; - break; - case 17: - if (Unit* car = Unit::GetCreature(*me, carGUID)) - { - me->SetFacingToObject(car); - car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ() + 1); - car->StopMoving(); - car->RemoveAura(SPELL_CART_DRAG); - } - Talk(SAY_SCARLET_MINER_1); - break; - default: - break; + switch (waypointId) + { + case 1: + if (Unit* car = ObjectAccessor::GetCreature(*me, carGUID)) + me->SetFacingToObject(car); + Talk(SAY_SCARLET_MINER_0); + SetRun(true); + IntroTimer = 4000; + IntroPhase = 1; + break; + case 17: + if (Unit* car = ObjectAccessor::GetCreature(*me, carGUID)) + { + me->SetFacingToObject(car); + car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ() + 1); + car->StopMoving(); + car->RemoveAura(SPELL_CART_DRAG); + } + Talk(SAY_SCARLET_MINER_1); + break; + default: + break; + } } - } - void UpdateAI(uint32 diff) - { - if (IntroPhase) + void UpdateAI(uint32 diff) { - if (IntroTimer <= diff) + if (IntroPhase) { - if (IntroPhase == 1) + if (IntroTimer <= diff) { - if (Creature* car = Unit::GetCreature(*me, carGUID)) - DoCast(car, SPELL_CART_DRAG); - IntroTimer = 800; - IntroPhase = 2; + if (IntroPhase == 1) + { + if (Creature* car = Unit::GetCreature(*me, carGUID)) + DoCast(car, SPELL_CART_DRAG); + IntroTimer = 800; + IntroPhase = 2; + } + else + { + if (Creature* car = Unit::GetCreature(*me, carGUID)) + car->AI()->DoAction(0); + IntroPhase = 0; + } } else - { - if (Creature* car = Unit::GetCreature(*me, carGUID)) - car->AI()->DoAction(0); - IntroPhase = 0; - } - } else IntroTimer-=diff; + IntroTimer -= diff; + } + npc_escortAI::UpdateAI(diff); } - npc_escortAI::UpdateAI(diff); - } - }; + }; -}; - -/*###### -## go_inconspicuous_mine_car -######*/ - -enum Spells_Cart -{ - SPELL_CART_SUMM = 52463 -}; - -class go_inconspicuous_mine_car : public GameObjectScript -{ -public: - go_inconspicuous_mine_car() : GameObjectScript("go_inconspicuous_mine_car") { } - - bool OnGossipHello(Player* player, GameObject* /*go*/) - { - if (player->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) + CreatureAI* GetAI(Creature* creature) const { - // Hack Why Trinity Dont Support Custom Summon Location - if (Creature* miner = player->SummonCreature(28841, 2383.869629f, -5900.312500f, 107.996086f, player->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1)) - { - player->CastSpell(player, SPELL_CART_SUMM, true); - if (Creature* car = player->GetVehicleCreatureBase()) - { - if (car->GetEntry() == 28817) - { - car->AI()->SetGUID(miner->GetGUID()); - CAST_AI(npc_scarlet_miner::npc_scarlet_minerAI, miner->AI())->InitCartQuest(player); - } else sLog->outError(LOG_FILTER_TSCR, "OnGossipHello vehicle entry is not correct."); - } else sLog->outError(LOG_FILTER_TSCR, "OnGossipHello player is not on the vehicle."); - } else sLog->outError(LOG_FILTER_TSCR, "OnGossipHello Scarlet Miner cant be found by script."); + return new npc_scarlet_minerAI(creature); } - return true; - } - }; // npc 28912 quest 17217 boss 29001 mob 29007 go 191092 @@ -1101,5 +1092,4 @@ void AddSC_the_scarlet_enclave_c1() new npc_scarlet_ghoul(); new npc_scarlet_miner(); new npc_scarlet_miner_cart(); - new go_inconspicuous_mine_car(); } diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp index 7af7e1e78bc..156d31c804f 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp @@ -98,34 +98,32 @@ public: npc_shadowfang_prisonerAI(Creature* creature) : npc_escortAI(creature) { instance = creature->GetInstanceScript(); - uiNpcEntry = creature->GetEntry(); } InstanceScript* instance; - uint32 uiNpcEntry; void WaypointReached(uint32 waypointId) { switch (waypointId) { case 0: - if (uiNpcEntry == NPC_ASH) + if (me->GetEntry() == NPC_ASH) Talk(SAY_FREE_AS); else Talk(SAY_FREE_AD); break; case 10: - if (uiNpcEntry == NPC_ASH) + if (me->GetEntry() == NPC_ASH) Talk(SAY_OPEN_DOOR_AS); else Talk(SAY_OPEN_DOOR_AD); break; case 11: - if (uiNpcEntry == NPC_ASH) + if (me->GetEntry() == NPC_ASH) DoCast(me, SPELL_UNLOCK); break; case 12: - if (uiNpcEntry == NPC_ASH) + if (me->GetEntry() == NPC_ASH) Talk(SAY_POST_DOOR_AS); else Talk(SAY_POST1_DOOR_AD); @@ -134,7 +132,7 @@ public: instance->SetData(TYPE_FREE_NPC, DONE); break; case 13: - if (uiNpcEntry != NPC_ASH) + if (me->GetEntry() != NPC_ASH) Talk(SAY_POST2_DOOR_AD); break; } diff --git a/src/server/scripts/Events/childrens_week.cpp b/src/server/scripts/Events/childrens_week.cpp index 2ec5e1190c8..2ef776e4e76 100644 --- a/src/server/scripts/Events/childrens_week.cpp +++ b/src/server/scripts/Events/childrens_week.cpp @@ -684,7 +684,6 @@ class npc_the_etymidian : public CreatureScript private: uint32 timer; int8 phase; - uint32 GOtimer; uint64 playerGUID; uint64 orphanGUID; @@ -847,7 +846,6 @@ class npc_alexstraza_the_lifebinder : public CreatureScript uint32 timer; uint64 playerGUID; uint64 orphanGUID; - uint64 alexstraszaGUID; }; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 3d22bac4376..c335c90cc30 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -136,9 +136,7 @@ class boss_tyrannus : public CreatureScript void InitializeAI() { - if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(PoSScriptName)) - me->IsAIEnabled = false; - else if (instance->GetBossState(DATA_TYRANNUS) != DONE) + if (instance->GetBossState(DATA_TYRANNUS) != DONE) Reset(); else me->DespawnOrUnsummon(); @@ -281,7 +279,7 @@ class boss_tyrannus : public CreatureScript CreatureAI* GetAI(Creature* creature) const { - return new boss_tyrannusAI(creature); + return GetPitOfSaronAI<boss_tyrannusAI>(creature); } }; @@ -387,32 +385,32 @@ class boss_rimefang : public CreatureScript class player_overlord_brandAI : public PlayerAI { public: - player_overlord_brandAI(Player* player) : PlayerAI(player) + player_overlord_brandAI(Player* player) : PlayerAI(player), _tyrannus(0) { - tyrannus = NULL; } void SetGUID(uint64 guid, int32 /*type*/) { - tyrannus = ObjectAccessor::GetCreature(*me, guid); - me->IsAIEnabled = tyrannus != NULL; + _tyrannus = guid; } void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) { - if (tyrannus->getVictim()) - me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); + if (Creature* tyrannus = ObjectAccessor::GetCreature(*me, _tyrannus)) + if (tyrannus->getVictim()) + me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); } void HealDone(Unit* /*target*/, uint32& addHealth) { - me->CastCustomSpell(SPELL_OVERLORD_BRAND_HEAL, SPELLVALUE_BASE_POINT0, int32(addHealth*5.5f), tyrannus, true, NULL, NULL, tyrannus->GetGUID()); + if (Creature* tyrannus = ObjectAccessor::GetCreature(*me, _tyrannus)) + me->CastCustomSpell(SPELL_OVERLORD_BRAND_HEAL, SPELLVALUE_BASE_POINT0, int32(addHealth*5.5f), tyrannus, true, NULL, NULL, tyrannus->GetGUID()); } void UpdateAI(uint32 /*diff*/) { } private: - Creature* tyrannus; + uint64 _tyrannus; }; class spell_tyrannus_overlord_brand : public SpellScriptLoader @@ -424,6 +422,11 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader { PrepareAuraScript(spell_tyrannus_overlord_brand_AuraScript); + bool Load() + { + return GetCaster() && GetCaster()->GetEntry() == NPC_TYRANNUS; + } + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (GetTarget()->GetTypeId() != TYPEID_PLAYER) @@ -440,9 +443,10 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader if (GetTarget()->GetTypeId() != TYPEID_PLAYER) return; - delete GetTarget()->GetAI(); - GetTarget()->SetAI(oldAI); GetTarget()->IsAIEnabled = oldAIState; + UnitAI* thisAI = GetTarget()->GetAI(); + GetTarget()->SetAI(oldAI); + delete thisAI; } void Register() diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h index 94bca5ffaf7..a9b88ca3066 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -18,6 +18,9 @@ #ifndef DEF_PIT_OF_SARON_H #define DEF_PIT_OF_SARON_H +#include "Map.h" +#include "Creature.h" + #define PoSScriptName "instance_pit_of_saron" #define MAX_ENCOUNTER 3 @@ -94,4 +97,14 @@ enum GameObjectIds GO_HALLS_OF_REFLECTION_PORTCULLIS = 201848, }; +template<class AI> +AI* GetPitOfSaronAI(Creature* creature) +{ + if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(PoSScriptName)) + return new AI(creature); + return NULL; +} + #endif diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 8e8fb9ba9ac..4fbfe4219d4 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -73,7 +73,6 @@ enum Spells enum Shadowmourne { QUEST_BLOOD_INFUSION = 24756, - ITEM_SHADOW_S_EDGE = 49888, SPELL_GUSHING_WOUND = 72132, SPELL_THIRST_QUENCHED = 72154, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index ea74d8ec61c..7294e4a5571 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1131,7 +1131,8 @@ class spell_sindragosa_frost_breath : public SpellScriptLoader if (!target) return; - if (target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE) + // Check difficulty and quest status + if (!(target->GetRaidDifficulty() & RAID_DIFFICULTY_MASK_25MAN) || target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE) return; // Check if player has Shadow's Edge equipped and not ready for infusion diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 47fe7c8f80a..b558508f78a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -166,7 +166,7 @@ class boss_kologarn : public CreatureScript left = apply; if (!apply && isEncounterInProgress) { - who->ToCreature()->DisappearAndDie(); + who->ToCreature()->DespawnOrUnsummon(); Talk(SAY_LEFT_ARM_GONE); events.ScheduleEvent(EVENT_RESPAWN_LEFT_ARM, 40000); } @@ -177,7 +177,7 @@ class boss_kologarn : public CreatureScript right = apply; if (!apply && isEncounterInProgress) { - who->ToCreature()->DisappearAndDie(); + who->ToCreature()->DespawnOrUnsummon(); Talk(SAY_RIGHT_ARM_GONE); events.ScheduleEvent(EVENT_RESPAWN_RIGHT_ARM, 40000); } @@ -529,7 +529,7 @@ class spell_ulduar_stone_grip_absorb : public SpellScriptLoader //! What we do here is remove all harmful aura's related and teleport to safe spot. void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) return; if (!GetOwner()->ToCreature()) @@ -568,22 +568,30 @@ class spell_ulduar_stone_grip : public SpellScriptLoader owner->RemoveAurasDueToSpell(aurEff->GetAmount()); } - void OnRemoveVehicle(AuraEffect const* /*aurEff*/, AuraEffectHandleModes mode) + void OnRemoveVehicle(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (!(mode & AURA_EFFECT_HANDLE_REAL)) - return; - - if (GetOwner()->GetTypeId() != TYPEID_UNIT) + PreventDefaultAction(); + Unit* caster = GetCaster(); + if (!caster) return; - Player* caster = GetCaster() ? GetCaster()->ToPlayer() : NULL; - if (!caster || !caster->IsOnVehicle(GetOwner()->ToUnit())) - return; + Position exitPosition; + exitPosition.m_positionX = 1750.0f; + exitPosition.m_positionY = -7.5f + frand(-3.0f, 3.0f); + exitPosition.m_positionZ = 457.9322f; + // Remove pending passengers before exiting vehicle - might cause an Uninstall + GetTarget()->GetVehicleKit()->RemovePendingEventsForPassenger(caster); + caster->_ExitVehicle(&exitPosition); caster->RemoveAurasDueToSpell(GetId()); - caster->ExitVehicle(); - caster->GetMotionMaster()->MoveJump(1756.25f + irand(-3, 3), -8.3f + irand(-3, 3), 448.8f, 5.0f, 5.0f); - PreventDefaultAction(); + + // Temporarily relocate player to vehicle exit dest serverside to send proper fall movement + // beats me why blizzard sends these 2 spline packets one after another instantly + Position oldPos; + caster->GetPosition(&oldPos); + caster->Relocate(exitPosition); + caster->GetMotionMaster()->MoveFall(); + caster->Relocate(oldPos); } void Register() diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 215630ac5fa..dfb12a03c33 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -30,13 +30,12 @@ enum Yells { //Yells Ingvar YELL_AGGRO_1 = 0, - YELL_AGGRO_2 = 1, - + YELL_KILL_1 = 1, YELL_DEAD_1 = 2, - YELL_DEAD_2 = 3, - YELL_KILL_1 = 4, - YELL_KILL_2 = 5, + YELL_AGGRO_2 = 0, + YELL_KILL_2 = 1, + YELL_DEAD_2 = 2 }; enum Creatures diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index ce0eaefac90..1b944f9babb 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -40,7 +40,7 @@ enum WGqueuenpctext WG_NPCQUEUE_TEXT_A_NOWAR = 14782, WG_NPCQUEUE_TEXT_A_QUEUE = 14791, WG_NPCQUEUE_TEXT_A_WAR = 14781, - WG_NPCQUEUE_TEXTOPTION_JOIN = -1850507, + WG_NPCQUEUE_TEXTOPTION_JOIN = 20077, }; enum Spells diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index 4af11191708..1fb0210bb73 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Shattrath_City SD%Complete: 100 -SDComment: Quest support: 10004, 10009, 10211, 10231. Flask vendors, Teleport to Caverns of Time +SDComment: Quest support: 10004, 10009, 10211. Flask vendors, Teleport to Caverns of Time SDCategory: Shattrath City EndScriptData */ @@ -29,7 +29,6 @@ npc_salsalabim npc_shattrathflaskvendors npc_zephyr npc_kservant -npc_dirty_larry npc_ishanah npc_khadgar EndContentData */ @@ -425,198 +424,6 @@ public: }; /*###### -# npc_dirty_larry -######*/ - -#define GOSSIP_BOOK "Ezekiel said that you might have a certain book..." - -enum DirtyLarry -{ - SAY_1 = 0, - SAY_2 = 1, - SAY_3 = 2, - SAY_4 = 3, - SAY_5 = 4, - SAY_GIVEUP = 5, - - QUEST_WBI = 10231, - NPC_CREEPJACK = 19726, - NPC_MALONE = 19725 -}; - -class npc_dirty_larry : public CreatureScript -{ -public: - npc_dirty_larry() : CreatureScript("npc_dirty_larry") { } - - struct npc_dirty_larryAI : public ScriptedAI - { - npc_dirty_larryAI(Creature* creature) : ScriptedAI(creature) {} - - bool Event; - bool Attack; - bool Done; - - uint64 PlayerGUID; - - uint32 SayTimer; - uint32 Step; - - void Reset() - { - Event = false; - Attack = false; - Done = false; - - PlayerGUID = 0; - SayTimer = 0; - Step = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setFaction(1194); - if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) - { - Creepjack->AI()->EnterEvadeMode(); - Creepjack->setFaction(1194); - Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) - { - Malone->AI()->EnterEvadeMode(); - Malone->setFaction(1194); - Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - uint32 NextStep(uint32 Step) - { - Player* player = Unit::GetPlayer(*me, PlayerGUID); - - switch (Step) - { - case 0:{ me->SetInFront(player); - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - Creepjack->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) - Malone->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); }return 2000; - case 1: Talk(SAY_1, player->GetGUID()); return 3000; - case 2: Talk(SAY_2, player->GetGUID()); return 5000; - case 3: Talk(SAY_3, player->GetGUID()); return 2000; - case 4: Talk(SAY_4, player->GetGUID()); return 2000; - case 5: Talk(SAY_5, player->GetGUID()); return 2000; - case 6: Attack = true; return 2000; - default: return 0; - } - } - - void EnterCombat(Unit* /*who*/){} - - void UpdateAI(uint32 diff) - { - if (SayTimer <= diff) - { - if (Event) - SayTimer = NextStep(++Step); - } - else - SayTimer -= diff; - - if (Attack) - { - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) - { - if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) - { - Creepjack->Attack(player, true); - Creepjack->setFaction(14); - Creepjack->GetMotionMaster()->MoveChase(player); - Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) - { - Malone->Attack(player, true); - Malone->setFaction(14); - Malone->GetMotionMaster()->MoveChase(player); - Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - DoStartMovement(player); - AttackStart(player); - } - Attack = false; - } - - if (HealthBelowPct(5) && !Done) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAllAuras(); - - if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) - { - Creepjack->AI()->EnterEvadeMode(); - Creepjack->setFaction(1194); - Creepjack->GetMotionMaster()->MoveTargetedHome(); - Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) - { - Malone->AI()->EnterEvadeMode(); - Malone->setFaction(1194); - Malone->GetMotionMaster()->MoveTargetedHome(); - Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - me->setFaction(1194); - Done = true; - Talk(SAY_GIVEUP); - me->DeleteThreatList(); - me->CombatStop(); - me->GetMotionMaster()->MoveTargetedHome(); - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) - player->GroupEventHappens(QUEST_WBI, me); - } - DoMeleeAttackIfReady(); - } - }; - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - CAST_AI(npc_dirty_larry::npc_dirty_larryAI, creature->AI())->Event = true; - CAST_AI(npc_dirty_larry::npc_dirty_larryAI, creature->AI())->PlayerGUID = player->GetGUID(); - player->CLOSE_GOSSIP_MENU(); - } - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_WBI) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BOOK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_dirty_larryAI (creature); - } -}; - -/*###### # npc_ishanah ######*/ @@ -727,7 +534,6 @@ void AddSC_shattrath_city() new npc_shattrathflaskvendors(); new npc_zephyr(); new npc_kservant(); - new npc_dirty_larry(); new npc_ishanah(); new npc_khadgar(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 7d7cdb84861..a84f299167e 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -3585,6 +3585,55 @@ class spell_gen_darkflight : public SpellScriptLoader } }; +enum OrcDisguiseSpells +{ + SPELL_ORC_DISGUISE_TRIGGER = 45759, + SPELL_ORC_DISGUISE_MALE = 45760, + SPELL_ORC_DISGUISE_FEMALE = 45762, +}; + +class spell_gen_orc_disguise : public SpellScriptLoader +{ + public: + spell_gen_orc_disguise() : SpellScriptLoader("spell_gen_orc_disguise") { } + + class spell_gen_orc_disguise_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_orc_disguise_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ORC_DISGUISE_TRIGGER) || !sSpellMgr->GetSpellInfo(SPELL_ORC_DISGUISE_MALE) || + !sSpellMgr->GetSpellInfo(SPELL_ORC_DISGUISE_FEMALE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + if (Player* target = GetHitPlayer()) + { + uint8 gender = target->getGender(); + if (!gender) + caster->CastSpell(target, SPELL_ORC_DISGUISE_MALE, true); + else + caster->CastSpell(target, SPELL_ORC_DISGUISE_FEMALE, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_orc_disguise_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_orc_disguise_SpellScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -3672,4 +3721,5 @@ void AddSC_generic_spell_scripts() new spell_gen_running_wild(); new spell_gen_two_forms(); new spell_gen_darkflight(); + new spell_gen_orc_disguise(); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 811032f11c9..9704b709959 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -165,12 +165,15 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_NAME_BY_GUID, "UPDATE characters SET name = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC); // Guild handling // 0: uint32, 1: string, 2: uint32, 3: string, 4: string, 5: uint64, 6-10: uint32, 11: uint64 PrepareStatement(CHAR_INS_GUILD, "INSERT INTO guild (guildid, name, leaderguid, info, motd, createdate, EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, BankMoney) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GUILD, "DELETE FROM guild WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32 + // 0: string, 1: uint32 + PrepareStatement(CHAR_UPD_GUILD_NAME, "UPDATE guild SET name = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32, 2: uint8, 4: string, 5: string PrepareStatement(CHAR_INS_GUILD_MEMBER, "INSERT INTO guild_member (guildid, guid, rank, pnote, offnote) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32 diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index ad146b8e98f..d9900d53f46 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -161,11 +161,13 @@ enum CharacterDatabaseStatements CHAR_SEL_MATCH_MAKER_RATING, CHAR_SEL_CHARACTER_COUNT, CHAR_UPD_NAME, + CHAR_UPD_NAME_BY_GUID, CHAR_DEL_DECLINED_NAME, CHAR_SEL_CHARACTER_DATA_BY_GUID, CHAR_INS_GUILD, CHAR_DEL_GUILD, + CHAR_UPD_GUILD_NAME, CHAR_INS_GUILD_MEMBER, CHAR_DEL_GUILD_MEMBER, CHAR_DEL_GUILD_MEMBERS, diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index a23294a038c..0118f637205 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -37,7 +37,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.sessionkey, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.last_ip, aa.gmlevel, a.v, a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.lock_country, a.last_ip, aa.gmlevel, a.v, a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_FAILEDLOGINS, "SELECT id, failed_logins FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); @@ -59,6 +60,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY, "UPDATE account SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET v = 0, s = 0, username = ?, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_PASSWORD, "UPDATE account SET v = 0, s = 0, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); @@ -88,6 +90,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h index 939cc4b4790..97cf91fc178 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/shared/Database/Implementation/LoginDatabase.h @@ -56,6 +56,7 @@ enum LoginDatabaseStatements LOGIN_UPD_VS, LOGIN_UPD_LOGONPROOF, LOGIN_SEL_LOGONCHALLENGE, + LOGIN_SEL_LOGON_COUNTRY, LOGIN_UPD_FAILEDLOGINS, LOGIN_SEL_FAILEDLOGINS, LOGIN_SEL_ACCOUNT_ID_BY_NAME, @@ -79,6 +80,7 @@ enum LoginDatabaseStatements LOGIN_INS_REALM_CHARACTERS_INIT, LOGIN_UPD_EXPANSION, LOGIN_UPD_ACCOUNT_LOCK, + LOGIN_UPD_ACCOUNT_LOCK_CONTRY, LOGIN_INS_LOG, LOGIN_UPD_USERNAME, LOGIN_UPD_PASSWORD, @@ -108,6 +110,8 @@ enum LoginDatabaseStatements LOGIN_SEL_ACCOUNT_WHOIS, LOGIN_SEL_REALMLIST_SECURITY_LEVEL, LOGIN_DEL_ACCOUNT, + LOGIN_SEL_IP2NATION_COUNTRY, + LOGIN_SEL_AUTOBROADCAST, LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, LOGIN_SEL_RBAC_ACCOUNT_GROUPS, diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index 94c01dd6569..c6e520cfdde 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -80,7 +80,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index 032baf29dd9..d8c3c69dbba 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -100,7 +100,6 @@ enum WorldDatabaseStatements WORLD_SEL_COMMANDS, WORLD_SEL_CREATURE_TEMPLATE, WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, - WORLD_SEL_IP2NATION_COUNTRY, WORLD_SEL_ITEM_TEMPLATE_BY_NAME, WORLD_SEL_CREATURE_BY_ID, WORLD_SEL_GAMEOBJECT_NEAREST, diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 840ae6ad0b6..1f9231ac0b8 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -196,7 +196,7 @@ endif() if( UNIX ) install(TARGETS worldserver DESTINATION bin) - install(FILES worldserver.conf.dist DESTINATION etc) + install(FILES worldserver.conf.dist DESTINATION ${CONF_DIR}) elseif( WIN32 ) install(TARGETS worldserver DESTINATION "${CMAKE_INSTALL_PREFIX}") install(FILES worldserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}") diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 448ea2930e3..622070c121d 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2340,13 +2340,21 @@ CharDelete.Method = 0 # # CharDelete.MinLevel -# Description: Required level to use the unlinking method if enabled. +# Description: Required level to use the unlinking method if enabled for non-heroic classes. # Default: 0 - (Same method for every level) # 1+ - (Only characters with the specified level will use the unlinking method) CharDelete.MinLevel = 0 # +# CharDelete.Heroic.MinLevel +# Description: Required level to use the unlinking method if enabled for heroic classes. +# Default: 0 - (Same method for every level) +# 1+ - (Only characters with the specified level will use the unlinking method) + +CharDelete.Heroic.MinLevel = 0 + +# # CharDelete.KeepDays # Description: Time (in days) before unlinked characters will be removed from the database. # Default: 30 - (Enabled) |