memory_xsb.c

00001 /* File:      memory_xsb.c
00002 ** Author(s): Ernie Johnson, Swift, Xu, Sagonas
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** Copyright (C) ECRC, Germany, 1990
00007 ** 
00008 ** XSB is free software; you can redistribute it and/or modify it under the
00009 ** terms of the GNU Library General Public License as published by the Free
00010 ** Software Foundation; either version 2 of the License, or (at your option)
00011 ** any later version.
00012 ** 
00013 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00014 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00015 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00016 ** more details.
00017 ** 
00018 ** You should have received a copy of the GNU Library General Public License
00019 ** along with XSB; if not, write to the Free Software Foundation,
00020 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 **
00022 ** $Id: memory_xsb.c,v 1.30 2006/07/25 14:25:54 dwarren Exp $
00023 ** 
00024 */
00025 
00026 
00027 /*======================================================================*/
00028 /* This module provides abstractions of memory management functions     */
00029 /* for the abstract machine.  The following interface routines are      */
00030 /* exported:                                                            */
00031 /*      Program area handling:                                          */
00032 /*          mem_alloc(size,cat):  alloc size bytes (on 8 byte boundary) */
00033 /*          mem_dealloc(addr,size,cat):  dealloc space                  */
00034 /*      Stack area:                                                     */
00035 /*          tcpstack_realloc(size)                                      */
00036 /*          complstack_realloc(size)                                    */
00037 /*======================================================================*/
00038 
00039 /* xsb_config.h must be the first #include.  Please don't move it. */
00040 #include "xsb_config.h"    /* needed by "cell_xsb.h" */
00041 #include "xsb_debug.h"
00042 
00043 
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 
00048 #include "auxlry.h"
00049 #include "binding.h"
00050 #include "cell_xsb.h"
00051 #include "memory_xsb.h"
00052 #include "register.h"
00053 #include "psc_xsb.h"
00054 #include "tries.h"     /* needed by "choice.h" */
00055 #include "choice.h"
00056 #include "error_xsb.h"
00057 #include "macro_xsb.h"
00058 #include "thread_xsb.h"
00059 
00060 #include "flags_xsb.h"
00061 #include "subp.h"
00062 #include "debug_xsb.h"
00063 
00064 #if defined(GENERAL_TAGGING)
00065 extern long int next_free_code;
00066 extern unsigned long enc[], dec[];
00067 
00068 void inline extend_enc_dec_as_nec(void *lptr, void *hptr) {
00069     unsigned long nibble;
00070     unsigned long lnibble = (unsigned long)lptr >> 28;
00071     unsigned long hnibble = (unsigned long)hptr >> 28;
00072     for (nibble = lnibble; nibble <= hnibble; nibble++) {
00073       if (enc[nibble] == -1) {
00074         SYS_MUTEX_LOCK_NOERROR(MUTEX_GENTAG);
00075         if (enc[nibble] == -1) { /* be sure not changed since test */
00076           enc[nibble] = next_free_code << 28;
00077           dec[next_free_code] = nibble << 28;
00078           // printf("recoding %lx to %lx\n",nibble,next_free_code);
00079           next_free_code++;
00080         }
00081         SYS_MUTEX_UNLOCK_NOERROR(MUTEX_GENTAG);
00082       }
00083     }
00084 }
00085 #endif
00086 
00087 /* === alloc permanent memory ============================================== */
00088 
00089 /* TLS: NOERROR locking done in mem_xxxoc() will not cause concurrency
00090    problems -- we just need to check for null ptr values and possibly
00091    abort after unlocking (when we check -- we're sometimes a little
00092    sloppy). */
00093 
00094 void *mem_alloc(unsigned long size, int category)
00095 {
00096     byte * ptr;
00097 
00098     size = (size+7) & ~0x7 ;          /* round to 8 */
00099 
00100 #ifdef NON_OPT_COMPILE
00101     SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00102 #endif
00103     pspacesize[category] += size;
00104 
00105     ptr = (byte *) malloc(size);
00106 
00107 #if defined(GENERAL_TAGGING)
00108     //    printf("mem_alloc %x %x\n",ptr,ptr+size);
00109     extend_enc_dec_as_nec(ptr,ptr+size);
00110 #endif
00111 
00112 #ifdef NON_OPT_COMPILE
00113     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00114 #endif
00115 
00116     if (ptr == NULL && size > 0) {
00117       xsb_memory_error("memory","mem_alloc()");
00118     }
00119     return ptr;
00120 }
00121 
00122 
00123 /* TLS: does not check returns -- for use in error messages and
00124    throw */
00125 void *mem_alloc_nocheck(unsigned long size, int category)
00126 {
00127     byte * ptr;
00128 
00129     size = (size+7) & ~0x7 ;          /* round to 8 */
00130 #ifdef NON_OPT_COMPILE
00131     SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00132 #endif
00133     pspacesize[category] += size;
00134     ptr = (byte *) malloc(size);
00135 #if defined(GENERAL_TAGGING)
00136     //    printf("mem_alloc %x %x\n",ptr,ptr+size);
00137     extend_enc_dec_as_nec(ptr,ptr+size);
00138 #endif
00139 #ifdef NON_OPT_COMPILE
00140     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00141 #endif
00142     return ptr;
00143 }
00144 
00145 
00146 /* === calloc permanent memory ============================================= */
00147 
00148 void *mem_calloc(unsigned long size, unsigned long occs, int category)
00149 {
00150     byte * ptr;
00151     unsigned long length = (size*occs+7) & ~0x7;
00152 
00153 #ifdef NON_OPT_COMPILE
00154    SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00155 #endif
00156     pspacesize[category] += length;
00157     ptr = (byte *) calloc(size,occs);
00158 #if defined(GENERAL_TAGGING)
00159     //    printf("mem_calloc %x %x\n",ptr,ptr+length);
00160     extend_enc_dec_as_nec(ptr,ptr+length);
00161 #endif
00162 #ifdef NON_OPT_COMPILE
00163     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00164 #endif
00165     if (ptr == NULL && size > 0 && occs > 0) {
00166       xsb_memory_error("memory","mem_calloc()");
00167     }
00168     return ptr;
00169 }
00170 
00171 
00172 /* === realloc permanent memory ============================================ */
00173 
00174 void *mem_realloc(void *addr, unsigned long oldsize, unsigned long newsize, int category)
00175 {
00176     newsize = (newsize+7) & ~0x7 ;            /* round to 8 */
00177     oldsize = (oldsize+7) & ~0x7 ;            /* round to 8 */
00178 #ifdef NON_OPT_COMPILE
00179     SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00180 #endif
00181     pspacesize[category] = pspacesize[category] - oldsize + newsize;
00182     addr = (byte *) realloc(addr,newsize);
00183 #if defined(GENERAL_TAGGING)
00184     extend_enc_dec_as_nec(addr,addr+newsize);
00185 #endif
00186 #ifdef NON_OPT_COMPILE
00187     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00188 #endif
00189     if (addr == NULL && newsize > 0) {
00190       xsb_memory_error("memory","mem_realloc()");
00191     }
00192     return addr;
00193 }
00194 
00195 void *mem_realloc_nocheck(void *addr, unsigned long oldsize, unsigned long newsize, int category)
00196 {
00197     newsize = (newsize+7) & ~0x7 ;            /* round to 8 */
00198     oldsize = (oldsize+7) & ~0x7 ;            /* round to 8 */
00199 #ifdef NON_OPT_COMPILE
00200     SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00201 #endif
00202     pspacesize[category] = pspacesize[category] - oldsize + newsize;
00203     addr = (byte *) realloc(addr,newsize);
00204 #if defined(GENERAL_TAGGING)
00205     extend_enc_dec_as_nec(addr,addr+newsize);
00206 #endif
00207 #ifdef NON_OPT_COMPILE
00208     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00209 #endif
00210     return addr;
00211 }
00212 
00213 
00214 /* === dealloc permanent memory ============================================ */
00215 
00216 void mem_dealloc(void *addr, unsigned long size, int category)
00217 {
00218   //  int i;
00219     size = (size+7) & ~0x7 ;          /* round to 8 */
00220 #ifdef NON_OPT_COMPILE
00221     SYS_MUTEX_LOCK_NOERROR(MUTEX_MEM);
00222 #endif
00223     //    if (size > 0) for (i=0; i<size/4-1; i++) *((CPtr *)addr + i) = (CPtr)0xefefefef;
00224     pspacesize[category] -= size;
00225     free(addr);
00226 #ifdef NON_OPT_COMPILE
00227     SYS_MUTEX_UNLOCK_NOERROR(MUTEX_MEM);
00228 #endif
00229 }
00230 
00231 
00232 /* === reallocate stack memory ============================================= */
00233 
00234 /*
00235  * Re-allocate the space for the trail and choice point stack data area
00236  * to "new_size" K-byte blocks.
00237  */
00238 
00239 void tcpstack_realloc(CTXTdeclc long new_size) {
00240 
00241   byte *cps_top,         /* addr of topmost byte in old CP Stack */
00242        *trail_top;       /* addr of topmost frame (link field) in old Trail */
00243 
00244   byte *new_trail,        /* bottom of new trail area */
00245        *new_cps;          /* bottom of new choice point stack area */
00246 
00247   long trail_offset,      /* byte offsets between the old and new */
00248        cps_offset;        /*   stack bottoms */
00249 
00250   CPtr *trail_link;    /* for stepping thru Trail and altering dyn links */
00251   CPtr *cell_ptr;      /* for stepping thru CPStack and altering cell values */
00252   byte *cell_val;      /* consider each cell to contain a ptr value */
00253 
00254   ComplStackFrame csf_ptr;    /* for stepping through the ComplStack */
00255   VariantSF subg_ptr;         /* and altering the CP ptrs in the SGFs */
00256 
00257   if (new_size == tcpstack.size)
00258     return;
00259 
00260   cps_top = (byte *)top_of_cpstack;
00261   trail_top = (byte *)top_of_trail;
00262 
00263   xsb_dbgmsg((LOG_DEBUG,
00264              "Reallocating the Trail and Choice Point Stack data area"));
00265 
00266   /* Expand the Trail / Choice Point Stack Area
00267      ------------------------------------------ */
00268   if (new_size > tcpstack.size) {
00269     if (tcpstack.size == tcpstack.init_size) {
00270       xsb_dbgmsg((LOG_DEBUG, "\tBottom:\t\t%p\t\tInitial Size: %ldK",
00271                  tcpstack.low, tcpstack.size));
00272       xsb_dbgmsg((LOG_DEBUG, "\tTop:\t\t%p", tcpstack.high));
00273     }
00274     /*
00275      * Increase the size of the data area and push the Choice Point Stack
00276      * to its high-memory end.
00277      *
00278      * 'realloc' copies the data in the reallocated region to the new region.
00279      * 'memmove' can perform an overlap copy: we take the choice point data
00280      *   from where it was moved and push it to the high end of the newly
00281      *   allocated region.
00282      */
00283     new_trail = (byte *)realloc(tcpstack.low, new_size * K);
00284     if ( IsNULL(new_trail) )
00285       xsb_exit("Not enough core to resize the Trail and Choice Point Stack!");
00286     new_cps = new_trail + new_size * K;
00287 
00288 #if defined(GENERAL_TAGGING)
00289     // seems not nec (any tagged pointers into here?)
00290     //       printf("tcpstack_realloc %p %p\n",new_trail,new_cps);
00291     //       extend_enc_dec_as_nec(new_trail,new_cps);
00292 #endif
00293 
00294     trail_offset = (long)(new_trail - tcpstack.low);
00295     cps_offset = (long)(new_cps - tcpstack.high);
00296     memmove(cps_top + cps_offset,              /* move to */
00297             cps_top + trail_offset,            /* move from */
00298             (long)(tcpstack.high - cps_top) ); /* number of bytes */
00299   }
00300   /* Compact the Trail / Choice Point Stack Area
00301      ------------------------------------------- */
00302   else {
00303     /*
00304      * Float the Choice Point Stack data up to lower-memory and reduce the
00305      * size of the data area.
00306      */
00307     memmove(cps_top - (tcpstack.size - new_size) * K,  /* move to */
00308             cps_top,                                   /* move from */
00309             (long)(tcpstack.high - cps_top) );         /* number of bytes */
00310     new_trail = (byte *)realloc(tcpstack.low, new_size * K);
00311     trail_offset = (long)(new_trail - tcpstack.low);
00312     new_cps = new_trail + new_size * K;
00313     cps_offset = (long)(new_cps - tcpstack.high);
00314   }
00315 
00316   /* Update the Trail links
00317      ---------------------- */
00318   /*
00319    *  Start at the base of the Trail and work up.  The base has a self-
00320    *  pointer to mark the bottom of the Trail.  The TRx reg's point to the
00321    *  previous-link field of the Trail frames (i.e., the last field).
00322    */
00323   if (trail_offset != 0) {
00324     for (trail_link = (CPtr *)(trail_top + trail_offset);
00325          trail_link > (CPtr *)new_trail;
00326          trail_link = trail_link - 3) {
00327       *trail_link = (CPtr)((byte *)*trail_link + trail_offset);
00328       if ((Cell)*(trail_link-2) & PRE_IMAGE_MARK) trail_link--;
00329     }
00330   }
00331 
00332   /* Update the pointers in the CP Stack
00333      ----------------------------------- */
00334   /*
00335    *  Start at the top of the CP Stack and work down, stepping through
00336    *  each field of every frame on the stack.  Any field containing a
00337    *  pointer either into the Trail or CP Stack must be updated.
00338    *  Bx reg's point to the first field of any CP frame.
00339    */
00340   for (cell_ptr = (CPtr *)(cps_top + cps_offset);
00341        cell_ptr < (CPtr *)new_cps;
00342        cell_ptr++) {
00343     
00344     cell_val = (byte *)*cell_ptr;
00345     if(isref(cell_val)) {
00346       /*
00347        *  If the cell points into the CP Stack, adjust with offset.
00348        */
00349       if ( (cell_val >= cps_top) && (cell_val < tcpstack.high) )
00350         *cell_ptr = (CPtr)(cell_val + cps_offset);
00351       /*
00352        *  If the cell points into the Trail, adjust with offset.
00353        */
00354       else if ( (cell_val >= tcpstack.low) && (cell_val <= trail_top) )
00355         *cell_ptr = (CPtr)(cell_val + trail_offset);
00356       /*
00357        *  If the cell points into the region between the two stacks, then
00358        *  this may signal a bug in the engine.
00359        */
00360       else if ( (cell_val < cps_top) && (cell_val > trail_top) )
00361         xsb_warn("During Trail / Choice Point Stack Reallocation\n\t   "
00362                  "Erroneous pointer:  Points between Trail and CP Stack tops"
00363                  "\n\t   Addr:%p, Value:%p", cell_ptr, cell_val);
00364     }
00365   }
00366 
00367   /* Update the Subgoal Frames' pointers into the CP Stack 
00368      ----------------------------------------------------- */
00369   for (csf_ptr = (ComplStackFrame)openreg;
00370        csf_ptr < (ComplStackFrame)complstack.high;
00371        csf_ptr++) {
00372 
00373     subg_ptr = compl_subgoal_ptr(csf_ptr);
00374     if ( IsNonNULL(subg_asf_list_ptr(subg_ptr)) )
00375       subg_asf_list_ptr(subg_ptr) =
00376         (CPtr)( (byte *)subg_asf_list_ptr(subg_ptr) + cps_offset );
00377 
00378     if ( IsNonNULL(subg_compl_susp_ptr(subg_ptr)) )
00379       subg_compl_susp_ptr(subg_ptr) =
00380         (CPtr)( (byte *)subg_compl_susp_ptr(subg_ptr) + cps_offset );
00381     if ( IsNonNULL(subg_cp_ptr(subg_ptr)) )
00382       subg_cp_ptr(subg_ptr) =
00383         (CPtr)((byte *)subg_cp_ptr(subg_ptr) + cps_offset);
00384   }
00385                                                      
00386   /* Update the system variables
00387      --------------------------- */
00388   tcpstack.low = new_trail;
00389   tcpstack.high = new_cps;
00390   tcpstack.size = new_size;
00391   
00392   trreg = (CPtr *)((byte *)trreg + trail_offset);
00393   breg = (CPtr)((byte *)breg + cps_offset);
00394   trfreg = (CPtr *)((byte *)trfreg + trail_offset);
00395   bfreg = (CPtr)((byte *)bfreg + cps_offset);
00396   if ( IsNonNULL(root_address) )
00397     root_address = (CPtr)((byte *)root_address + cps_offset);
00398 
00399   xsb_dbgmsg((LOG_DEBUG, "\tNew Bottom:\t%p\t\tNew Size: %ldK",
00400              tcpstack.low, tcpstack.size));
00401   xsb_dbgmsg((LOG_DEBUG, "\tNew Top:\t%p\n", tcpstack.high));
00402 }
00403 
00404 /* ------------------------------------------------------------------------- */
00405 
00406 void handle_tcpstack_overflow(CTXTdecl)
00407 {
00408   if (pflags[STACK_REALLOC]) {
00409     xsb_warn("Expanding the Trail and Choice Point Stack...");
00410     tcpstack_realloc(CTXTc resize_stack(tcpstack.size,0));
00411   }
00412   else {
00413     xsb_exit("Trail/ChoicePoint stack overflow detected but expansion is off");
00414   }
00415 }
00416 
00417 /* ------------------------------------------------------------------------- */
00418 
00419 /*
00420  * Re-allocate the space for the completion stack data area to "new_size"
00421  * K-byte blocks.
00422  */
00423 
00424 void complstack_realloc (CTXTdeclc long new_size) {
00425 
00426   byte *new_top,    /* bottom of new trail area */
00427   *new_bottom;      /* bottom of new choice point stack area */
00428 
00429   long top_offset,   /* byte offsets between the old and new */
00430   bottom_offset;    /*    stack bottoms */
00431 
00432   byte *cs_top;     /* ptr to topmost byte on the complstack */
00433 
00434   ComplStackFrame csf_ptr;
00435   VariantSF subg_ptr;
00436 
00437   
00438   if (new_size == complstack.size)
00439     return;
00440   
00441   cs_top = (byte *)top_of_complstk;
00442   
00443   xsb_dbgmsg((LOG_DEBUG, "Reallocating the Completion Stack"));
00444 
00445   /* Expand the Completion Stack
00446      --------------------------- */
00447   if (new_size > complstack.size) {
00448     if (complstack.size == complstack.init_size) { 
00449       xsb_dbgmsg((LOG_DEBUG, "\tBottom:\t\t%p\t\tInitial Size: %ldK",
00450                  complstack.low, complstack.size));
00451       xsb_dbgmsg((LOG_DEBUG, "\tTop:\t\t%p", complstack.high));
00452     }
00453 
00454     /*
00455      * Increase the size of the data area and push the Completion Stack
00456      * to its high-memory end.
00457      */
00458     new_top = (byte *)realloc(complstack.low, new_size * K);
00459     if ( IsNULL(new_top) )
00460       xsb_exit("Not enough core to resize the Completion Stack!");
00461     new_bottom = new_top + new_size * K;
00462     
00463     top_offset = (long)(new_top - complstack.low);
00464     bottom_offset = (long)(new_bottom - complstack.high);
00465     memmove(cs_top + bottom_offset,     /* move to */
00466             cs_top + top_offset,        /* move from */
00467             (long)(complstack.high - cs_top) );
00468   }
00469   /* Compact the Completion Stack
00470      ---------------------------- */
00471   else {
00472     /*
00473      * Float the Completion Stack data up to lower-memory and reduce the
00474      * size of the data area.
00475      */
00476     memmove(cs_top - (complstack.size - new_size) * K,  /* move to */
00477             cs_top,                                     /* move from */
00478             (long)(complstack.high - cs_top) );         /* number of bytes */
00479     new_top = (byte *)realloc(complstack.low, new_size * K);
00480     top_offset = (long)(new_top - complstack.low);
00481     new_bottom = new_top + new_size * K;
00482     bottom_offset = (long)(new_bottom - complstack.high);
00483   }
00484 
00485   /* Update subgoals' pointers into the completion stack
00486      --------------------------------------------------- */
00487   for (csf_ptr = (ComplStackFrame)(cs_top + bottom_offset);
00488        csf_ptr < (ComplStackFrame)new_bottom;
00489        csf_ptr++) {
00490     subg_ptr = compl_subgoal_ptr(csf_ptr);
00491     subg_compl_stack_ptr(subg_ptr) =
00492       (CPtr)((byte *)subg_compl_stack_ptr(subg_ptr) + bottom_offset);
00493   }
00494 
00495 
00496   /* Update the system variables
00497      --------------------------- */
00498   complstack.low = new_top;
00499   complstack.high = new_bottom;
00500   complstack.size = new_size;
00501   
00502   openreg = (CPtr)((byte *)openreg + bottom_offset);
00503 
00504   xsb_dbgmsg((LOG_DEBUG, "\tNew Bottom:\t%p\t\tNew Size: %ldK",
00505              complstack.low, complstack.size));
00506   xsb_dbgmsg((LOG_DEBUG, "\tNew Top:\t%p\n", complstack.high));
00507 }

Generated on Wed Jul 26 13:30:41 2006 for XSB by  doxygen 1.4.5