Ejemplo n.º 1
0
NodeStats subgoal_statistics(CTXTdeclc Structure_Manager *sm) {

  NodeStats sg_stats;
  TIFptr tif;
  int nSubgoals;
  VariantSF pProdSF;
  SubConsSF pConsSF;

  sg_stats = node_statistics(sm);
  nSubgoals = 0;
  SYS_MUTEX_LOCK( MUTEX_TABLE );				
  if ( sm == &smVarSF ) {
    for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
      if ( IsVariantPredicate(tif) )
	for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
	      pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
	  nSubgoals++;
  }
  /* No shared smProdSF or smConsSF in MT engine */
  else if ( sm == &smProdSF ) {
    for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
      if ( IsSubsumptivePredicate(tif) )
	for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
	      pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
	  nSubgoals++;
  }
  else if ( sm == &smConsSF ) {
    for ( tif = tif_list.first;  IsNonNULL(tif);  tif = TIF_NextTIF(tif) )
      if ( IsSubsumptivePredicate(tif) )
	for ( pProdSF = TIF_Subgoals(tif);  IsNonNULL(pProdSF);
	      pProdSF = (VariantSF)subg_next_subgoal(pProdSF) )
	  for ( pConsSF = subg_consumers(pProdSF);  IsNonNULL(pConsSF); 
		pConsSF = conssf_consumers(pConsSF) )
	    nSubgoals++;
  }
  else {
    SYS_MUTEX_UNLOCK( MUTEX_TABLE );				
    xsb_dbgmsg((LOG_DEBUG, "Incorrect use of subgoal_statistics()\n"
	       "SM does not contain subgoal frames"));
    return sg_stats;
  }

  SYS_MUTEX_UNLOCK( MUTEX_TABLE );				
  if ( NodeStats_NumUsedNodes(sg_stats) != (counter) nSubgoals )
    xsb_warn(CTXTc "Inconsistent Subgoal Frame Usage Calculations:\n"
	     "\tSubgoal Frame count mismatch");

  return sg_stats;
}
Ejemplo n.º 2
0
/* FD_SET the socket fds */
static void set_sockfd(CTXTdeclc int count)
{
  int i;
  
  SYS_MUTEX_LOCK(MUTEX_SOCKETS);
  FD_ZERO(&connections[count].readset);
  FD_ZERO(&connections[count].writeset);
  FD_ZERO(&connections[count].exceptionset);
  
  for (i=0; i< connections[count].sizer; i++) {
    /* turn on the bit in the fd_set */
    FD_SET(connections[count].read_fds[i], &connections[count].readset);
  }

  for (i=0; i< connections[count].sizew; i++) {
    /* turn on the bit in the fd_set */
    FD_SET(connections[count].write_fds[i], &connections[count].writeset);
  }

  for (i=0; i< connections[count].sizee; i++) {
    /* turn on the bit in the fd_set */
    FD_SET(connections[count].exception_fds[i],
	   &connections[count].exceptionset);
  }
  SYS_MUTEX_UNLOCK(MUTEX_SOCKETS);
}
Ejemplo n.º 3
0
/* initialize the array of the structure */
static void init_connections(CTXTdecl) 
{
  int i;  
  static int initialized = FALSE; /* This is only initialized once. */

  SYS_MUTEX_LOCK(MUTEX_SOCKETS);

  if (!initialized) {
    for (i=0; i<MAXCONNECT; i++) {
      connections[i].connection_name = NULL; 
      connections[i].maximum_fd=0;
      connections[i].empty_flag=TRUE;
      /*clear all FD_SET */
      FD_ZERO(&connections[i].readset);
      FD_ZERO(&connections[i].writeset);
      FD_ZERO(&connections[i].exceptionset);
      
      connections[i].read_fds = 0;
      connections[i].write_fds = 0 ;
      connections[i].exception_fds = 0; 
      connections[i].sizer= 0;
      connections[i].sizew = 0 ;
      connections[i].sizee = 0 ;
    }
    initialized = TRUE;
  }

  SYS_MUTEX_UNLOCK(MUTEX_SOCKETS);
}
Ejemplo n.º 4
0
void symbol_table_stats(CTXTdecl) {

  UInteger   i, symbols, bucket_contains, used_buckets, unused_buckets,
                  fullest_bucket_size, fullest_bucket_num, last_index;
  UInteger first_index;
  Pair pair_ptr;

  SYS_MUTEX_LOCK( MUTEX_SYMBOL ) ;

  symbols = used_buckets = unused_buckets = last_index = 0;
  fullest_bucket_size = fullest_bucket_num = 0;
  first_index = -1;
  
  for (i = 0; i < symbol_table.size; i++) {
    if (symbol_table.table[i] != NULL) {
      if (first_index == -1)
	first_index = i;
      last_index = i;
      used_buckets++;
      bucket_contains = 0;
      for (pair_ptr = (Pair)symbol_table.table[i];   pair_ptr != NULL;
	   pair_ptr = pair_next(pair_ptr)) {
	symbols++;
	bucket_contains++;
      }
      if (bucket_contains > fullest_bucket_size) {
	fullest_bucket_size = bucket_contains;
	fullest_bucket_num = i;
      }
    }
    else
      unused_buckets++;
  }
  printf("\nSymbol table statistics:");
  printf("\n------------------------\n");
  printf("Table Size:\t%" UIntfmt "\n", symbol_table.size);
  printf("Total Symbols:\t%" UIntfmt "\n", symbols);
  if (symbols != symbol_table.contains)
    printf("Symbol count incorrect in 'symbol_table': %" UIntfmt "\n",
	   symbol_table.contains);
  printf("\tused buckets:\t%" UIntfmt "  (range: [%" Intfmt", %" UIntfmt "])\n", used_buckets,
	 first_index, last_index);
  printf("\tunused buckets:\t%" UIntfmt "\n", unused_buckets);
  printf("\tmaximum bucket size:\t%" UIntfmt "  (#: %" UIntfmt ")\n", fullest_bucket_size, 
	 fullest_bucket_num);

 SYS_MUTEX_UNLOCK( MUTEX_SYMBOL ) ;

}  
Ejemplo n.º 5
0
void string_table_stats(CTXTdecl) {

  UInteger   i, strings, bucket_contains, used_buckets, unused_buckets,
                  fullest_bucket_size, fullest_bucket_num, last_index;
  UInteger first_index;
  void *ptr;

 SYS_MUTEX_LOCK( MUTEX_STRING ) ;

  strings = used_buckets = unused_buckets = last_index = 0;
  fullest_bucket_size = fullest_bucket_num = 0;
  first_index = -1;
  
  for (i = 0; i < string_table.size; i++) {
    if (string_table.table[i] != NULL) {
      if (first_index == -1)
	first_index = i;
      last_index = i;
      used_buckets++;
      bucket_contains = 0;
      for (ptr = string_table.table[i];  ptr != NULL;  ptr = *(void **)ptr) {
	strings++;
	bucket_contains++;
      }
      if (bucket_contains > fullest_bucket_size) {
	fullest_bucket_size = bucket_contains;
	fullest_bucket_num = i;
      }
    }
    else
      unused_buckets++;
  }
  printf("\nString table statistics:");
  printf("\n------------------------\n");
  printf("Table Size:\t%" UIntfmt "\n", string_table.size);
  printf("Total Strings:\t%" UIntfmt "\n", strings);
  if (strings != string_table.contains)
    printf("String count incorrect in 'string_table': %" UIntfmt "\n",
	   string_table.contains);
  printf("\tused buckets:\t%" UIntfmt "  (range: [%" Intfmt ", %" UIntfmt "])\n", used_buckets,
	 first_index, last_index);
  printf("\tunused buckets:\t%" UIntfmt "\n", unused_buckets);
  printf("\tmaximum bucket size:\t%" UIntfmt "  (#: %" UIntfmt ")\n", fullest_bucket_size, 
	 fullest_bucket_num);

 SYS_MUTEX_UNLOCK( MUTEX_STRING ) ;

}
Ejemplo n.º 6
0
/* utility function to destroy a select call */
static void select_destroy(CTXTdeclc char *connection_name)
{
  int i;
  int connectname_found = FALSE;

  SYS_MUTEX_LOCK(MUTEX_SOCKETS);
  for (i=0; i < MAXCONNECT; i++) {
    if(connections[i].empty_flag==FALSE) {
      /* find the matching connection_name to destroy */
      if (strcmp(connection_name, connections[i].connection_name) == 0) {
	connectname_found = TRUE;
	      
	/* destroy the corresponding structure */
	FD_ZERO(&connections[i].readset);
	FD_ZERO(&connections[i].writeset);
	FD_ZERO(&connections[i].exceptionset);

	connections[i].connection_name = NULL;
	connections[i].maximum_fd = 0;

	/* free the fds obtained by mem_alloc() */
	mem_dealloc(connections[i].read_fds,connections[i].sizer,OTHER_SPACE);
	mem_dealloc(connections[i].write_fds,connections[i].sizew,OTHER_SPACE);
	mem_dealloc(connections[i].exception_fds,connections[i].sizee,OTHER_SPACE); 
      
	connections[i].sizer = 0;
	connections[i].sizew = 0 ;
	connections[i].sizee = 0 ;

	connections[i].empty_flag = TRUE; /* set the destroyed slot to empty */
	break;
      }
    }
  }
  SYS_MUTEX_UNLOCK(MUTEX_SOCKETS);
  
  /* if no matching connection_name */
  if (!connectname_found)
    xsb_abort("[SOCKET_SELECT_DESTROY] connection `%s' doesn't exist", 
	      connection_name);
  
  SQUASH_LINUX_COMPILER_WARN(connectname_found) ; 
}
Ejemplo n.º 7
0
/* TLS: making a conservative guess at which system calls need to be
   mutexed.  I'm doing it whenever I see the process table altered or
   affected, so this is the data structure that its protecting.

   At some point, the SET_FILEPTRs should be protected against other
   threads closing that stream.  Perhaps for such things a
   thread-specific stream table should be used.
*/
xsbBool sys_system(CTXTdeclc int callno)
{
  //  int pid;
  Integer pid;

  switch (callno) {
  case PLAIN_SYSTEM_CALL: /* dumb system call: no communication with XSB */
    /* this call is superseded by shell and isn't used */
    ctop_int(CTXTc 3, system(ptoc_string(CTXTc 2)));
    return TRUE;
  case SLEEP_FOR_SECS:
#ifdef WIN_NT
    Sleep((int)iso_ptoc_int_arg(CTXTc 2,"sleep/1",1) * 1000);
#else
    sleep(iso_ptoc_int_arg(CTXTc 2,"sleep/1",1));
#endif
    return TRUE;
  case GET_TMP_FILENAME:
    ctop_string(CTXTc 2,tempnam(NULL,NULL));
    return TRUE;
  case IS_PLAIN_FILE:
  case IS_DIRECTORY:
  case STAT_FILE_TIME:
  case STAT_FILE_SIZE:
    return file_stat(CTXTc callno, ptoc_longstring(CTXTc 2));
  case EXEC: {
#ifdef HAVE_EXECVP
    /* execs a new process in place of XSB */
    char *params[MAX_SUBPROC_PARAMS+2];
    prolog_term cmdspec_term;
    int index = 0;
    
    cmdspec_term = reg_term(CTXTc 2);
    if (islist(cmdspec_term)) {
      prolog_term temp, head;
      char *string_head=NULL;

      if (isnil(cmdspec_term))
	xsb_abort("[exec] Arg 1 must not be an empty list.");
      
      temp = cmdspec_term;
      do {
	head = p2p_car(temp);
	temp = p2p_cdr(temp);
	if (isstring(head)) 
	  string_head = string_val(head);
	else
	  xsb_abort("[exec] non-string argument passed in list.");
	
	params[index++] = string_head;
	if (index > MAX_SUBPROC_PARAMS)
	  xsb_abort("[exec] Too many arguments.");
      } while (!isnil(temp));
      params[index] = NULL;
    } else if (isstring(cmdspec_term)) {
      char *string = string_val(cmdspec_term);
      split_command_arguments(string, params, "exec");
    } else
      xsb_abort("[exec] 1st argument should be term or list of strings.");

    if (execvp(params[0], params)) 
      xsb_abort("[exec] Exec call failed.");
#else
    xsb_abort("[exec] builtin not supported in this architecture.");
#endif
  }
    
  case SHELL: /* smart system call: like SPAWN_PROCESS, but returns error code
		 instead of PID. Uses system() rather than execvp.
		 Advantage: can pass arbitrary shell command. */
  case SPAWN_PROCESS: { /* spawn new process, reroute stdin/out/err to XSB */
    /* +CallNo=2, +ProcAndArgsList,
       -StreamToProc, -StreamFromProc, -StreamFromProcStderr,
       -Pid */
    static int pipe_to_proc[2], pipe_from_proc[2], pipe_from_stderr[2];
    int toproc_stream=-1, fromproc_stream=-1, fromproc_stderr_stream=-1;
    int pid_or_status;
    FILE *toprocess_fptr=NULL,
      *fromprocess_fptr=NULL, *fromproc_stderr_fptr=NULL;
    char *params[MAX_SUBPROC_PARAMS+2]; /* one for progname--0th member,
				       one for NULL termination*/
    prolog_term cmdspec_term, cmdlist_temp_term;
    prolog_term cmd_or_arg_term;
    xsbBool toproc_needed=FALSE, fromproc_needed=FALSE, fromstderr_needed=FALSE;
    char *cmd_or_arg=NULL, *shell_cmd=NULL;
    int idx = 0, tbl_pos;
    char *callname=NULL;
    xsbBool params_are_in_a_list=FALSE;

    SYS_MUTEX_LOCK( MUTEX_SYS_SYSTEM );

    init_process_table();

    if (callno == SPAWN_PROCESS)
      callname = "spawn_process/5";
    else
      callname = "shell/[1,2,5]";

    cmdspec_term = reg_term(CTXTc 2);
    if (islist(cmdspec_term))
      params_are_in_a_list = TRUE;
    else if (isstring(cmdspec_term))
      shell_cmd = string_val(cmdspec_term);
    else if (isref(cmdspec_term))
      xsb_instantiation_error(CTXTc callname,1);
    else    
      xsb_type_error(CTXTc "atom or list e.g. [command, arg, ...]",cmdspec_term,callname,1);
    
    // xsb_abort("[%s] Arg 1 must be an atom or a list [command, arg, ...]",
    // callname);

    /* the user can indicate that he doesn't want either of the streams created
       by putting an atom in the corresponding argument position */
    if (isref(reg_term(CTXTc 3)))
      toproc_needed = TRUE;
    if (isref(reg_term(CTXTc 4)))
      fromproc_needed = TRUE;
    if (isref(reg_term(CTXTc 5)))
      fromstderr_needed = TRUE;

    /* if any of the arg streams is already used by XSB, then don't create
       pipes --- use these streams instead. */
    if (isointeger(reg_term(CTXTc 3))) {
      SET_FILEPTR(toprocess_fptr, oint_val(reg_term(CTXTc 3)));
    }
    if (isointeger(reg_term(CTXTc 4))) {
      SET_FILEPTR(fromprocess_fptr, oint_val(reg_term(CTXTc 4)));
    }
    if (isointeger(reg_term(CTXTc 5))) {
      SET_FILEPTR(fromproc_stderr_fptr, oint_val(reg_term(CTXTc 5)));
    }

    if (!isref(reg_term(CTXTc 6)))
      xsb_type_error(CTXTc "variable (to return process id)",reg_term(CTXTc 6),callname,5);
    //      xsb_abort("[%s] Arg 5 (process id) must be a variable", callname);

    if (params_are_in_a_list) {
      /* fill in the params[] array */
      if (isnil(cmdspec_term))
	xsb_abort("[%s] Arg 1 must not be an empty list", callname);
      
      cmdlist_temp_term = cmdspec_term;
      do {
	cmd_or_arg_term = p2p_car(cmdlist_temp_term);
	cmdlist_temp_term = p2p_cdr(cmdlist_temp_term);
	if (isstring(cmd_or_arg_term)) {
	  cmd_or_arg = string_val(cmd_or_arg_term);
	}
	else 
	  xsb_abort("[%s] Non string list member in the Arg",
		    callname);
	
	params[idx++] = cmd_or_arg;
	if (idx > MAX_SUBPROC_PARAMS)
	  xsb_abort("[%s] Too many arguments passed to subprocess",
		    callname);
	
      } while (!isnil(cmdlist_temp_term));

      params[idx] = NULL; /* null termination */

    } else { /* params are in a string */
      if (callno == SPAWN_PROCESS)
	split_command_arguments(shell_cmd, params, callname);
      else {
	/* if callno==SHELL => call system() => don't split shell_cmd */
	params[0] = shell_cmd;
	params[1] = NULL;
      }
    }
    
    /* -1 means: no space left */
    if ((tbl_pos = get_free_process_cell()) < 0) {
      xsb_warn(CTXTc "Can't create subprocess because XSB process table is full");
      SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
      return FALSE;
    }

      /* params[0] is the progname */
    pid_or_status = xsb_spawn(CTXTc params[0], params, callno,
			      (toproc_needed ? pipe_to_proc : NULL),
			      (fromproc_needed ? pipe_from_proc : NULL),
			      (fromstderr_needed ? pipe_from_stderr : NULL),
			      toprocess_fptr, fromprocess_fptr,
			      fromproc_stderr_fptr);
      
    if (pid_or_status < 0) {
      xsb_warn(CTXTc "[%s] Subprocess creation failed, Error: %d, errno: %d, Cmd: %s", callname,pid_or_status,errno,params[0]);
      SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
      return FALSE;
    }

    if (toproc_needed) {
      toprocess_fptr = fdopen(pipe_to_proc[1], "w");
      toproc_stream =  xsb_intern_fileptr(CTXTc toprocess_fptr,callname,"pipe","w",CURRENT_CHARSET); 
      ctop_int(CTXTc 3, toproc_stream);
    }
    if (fromproc_needed) {
      fromprocess_fptr = fdopen(pipe_from_proc[0], "r");
      fromproc_stream =  xsb_intern_fileptr(CTXTc fromprocess_fptr,callname,"pipe","r",CURRENT_CHARSET); 
      ctop_int(CTXTc 4, fromproc_stream);
    }
    if (fromstderr_needed) {
      fromproc_stderr_fptr = fdopen(pipe_from_stderr[0], "r");
      fromproc_stderr_stream
	= xsb_intern_fileptr(CTXTc fromproc_stderr_fptr,callname,"pipe","r",CURRENT_CHARSET); 
      ctop_int(CTXTc 5, fromproc_stderr_stream);
    }
    ctop_int(CTXTc 6, pid_or_status);

    xsb_process_table.process[tbl_pos].pid = pid_or_status;
    xsb_process_table.process[tbl_pos].to_stream = toproc_stream;
    xsb_process_table.process[tbl_pos].from_stream = fromproc_stream;
    xsb_process_table.process[tbl_pos].stderr_stream = fromproc_stderr_stream;
    concat_array(CTXTc params, " ",
		 xsb_process_table.process[tbl_pos].cmdline,MAX_CMD_LEN);
    
    SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
    return TRUE;
  }

  case GET_PROCESS_TABLE: { /* sys_system(3, X). X is bound to the list
	       of the form [process(Pid,To,From,Stderr,Cmdline), ...] */
    int i;
    prolog_term table_term_tail, listHead;
    prolog_term table_term=reg_term(CTXTc 2);

    SYS_MUTEX_LOCK( MUTEX_SYS_SYSTEM );
    init_process_table();

    if (!isref(table_term))
      xsb_abort("[GET_PROCESS_TABLE] Arg 1 must be a variable");

    table_term_tail = table_term;
    for (i=0; i<MAX_SUBPROC_NUMBER; i++) {
      if (!FREE_PROC_TABLE_CELL(xsb_process_table.process[i].pid)) {
	c2p_list(CTXTc table_term_tail); /* make it into a list */
	listHead = p2p_car(table_term_tail);

	c2p_functor(CTXTc "process", 5, listHead);
	c2p_int(CTXTc xsb_process_table.process[i].pid, p2p_arg(listHead,1));
	c2p_int(CTXTc xsb_process_table.process[i].to_stream, p2p_arg(listHead,2));
	c2p_int(CTXTc xsb_process_table.process[i].from_stream, p2p_arg(listHead,3));
	c2p_int(CTXTc xsb_process_table.process[i].stderr_stream,
		p2p_arg(listHead,4));
	c2p_string(CTXTc xsb_process_table.process[i].cmdline, p2p_arg(listHead,5));

	table_term_tail = p2p_cdr(table_term_tail);
      }
    }
    c2p_nil(CTXTc table_term_tail); /* bind tail to nil */
    SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
    return p2p_unify(CTXTc table_term, reg_term(CTXTc 2));
  }

  case PROCESS_STATUS: {
    prolog_term pid_term=reg_term(CTXTc 2), status_term=reg_term(CTXTc 3);

    SYS_MUTEX_LOCK( MUTEX_SYS_SYSTEM );

    init_process_table();

    if (!(isointeger(pid_term)))
      xsb_abort("[PROCESS_STATUS] Arg 1 (process id) must be an integer");
    pid = (int)oint_val(pid_term);

    if (!isref(status_term))
      xsb_abort("[PROCESS_STATUS] Arg 2 (process status) must be a variable");
    
    switch (process_status(pid)) {
    case RUNNING:
      c2p_string(CTXTc "running", status_term);
      break;
    case STOPPED:
      c2p_string(CTXTc "stopped", status_term);
      break;
    case EXITED_NORMALLY:
      c2p_string(CTXTc "exited_normally", status_term);
      break;
    case EXITED_ABNORMALLY:
      c2p_string(CTXTc "exited_abnormally", status_term);
      break;
    case ABORTED:
      c2p_string(CTXTc "aborted", status_term);
      break;
    case INVALID:
      c2p_string(CTXTc "invalid", status_term);
      break;
    default:
      c2p_string(CTXTc "unknown", status_term);
    }
    SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
    return TRUE;
  }

  case PROCESS_CONTROL: {
    /* sys_system(PROCESS_CONTROL, +Pid, +Signal). Signal: wait, kill */
    int status;
    prolog_term pid_term=reg_term(CTXTc 2), signal_term=reg_term(CTXTc 3);

    SYS_MUTEX_LOCK( MUTEX_SYS_SYSTEM );
    init_process_table();

    if (!(isointeger(pid_term)))
      xsb_abort("[PROCESS_CONTROL] Arg 1 (process id) must be an integer");
    pid = (int)oint_val(pid_term);

    if (isstring(signal_term) && strcmp(string_val(signal_term), "kill")==0) {
      if (KILL_FAILED(pid)) {
	SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
	return FALSE;
      }
#ifdef WIN_NT
      CloseHandle((HANDLE) pid);
#endif
      SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
      return TRUE;
    }
    if (isconstr(signal_term)
	&& strcmp(p2c_functor(signal_term),"wait") == 0
	&& p2c_arity(signal_term)==1) {
      int exit_status;

      if (WAIT(pid, status) < 0) {
	SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
	return FALSE;
      }

#ifdef WIN_NT
      exit_status = status;
#else
      if (WIFEXITED(status))
	exit_status = WEXITSTATUS(status);
      else
	exit_status = -1;
#endif

      p2p_unify(CTXTc p2p_arg(signal_term,1), makeint(exit_status));
      SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
      return TRUE;
    }

    xsb_warn(CTXTc "[PROCESS_CONTROL] Arg 2: Invalid signal specification. Must be `kill' or `wait(Var)'");
    return FALSE;
  }
   
  case LIST_DIRECTORY: {
    /* assume all type- and mode-checking is done in Prolog */
    prolog_term handle = reg_term(CTXTc 2); /* ref for handle */
    char *dir_name = ptoc_longstring(CTXTc 3); /* +directory name */
    prolog_term filename = reg_term(CTXTc 4); /* reference for name of file */
    
    if (is_var(handle)) 
      return xsb_find_first_file(CTXTc handle,dir_name,filename);
    else
      return xsb_find_next_file(CTXTc handle,dir_name,filename);
  }

  default:
    xsb_abort("[SYS_SYSTEM] Wrong call number (an XSB bug)");
  } /* end case */
  return TRUE;
}
Ejemplo n.º 8
0
/* in order to save builtin numbers, create a single socket function with
 * options socket_request(SockOperation,....)  */
xsbBool xsb_socket_request(CTXTdecl)
{
  int ecode = 0;  /* error code for socket ops */
  int timeout_flag;
  SOCKET sock_handle;
  int domain, portnum;
  SOCKADDR_IN socket_addr;
  struct linger sock_linger_opt;
  int rc;
  char *message_buffer = NULL; /* initialized to keep compiler happy */
  UInteger msg_len = 0;	  /* initialized to keep compiler happy */
  char char_read;

  switch (ptoc_int(CTXTc 1)) {
  case SOCKET_ROOT: /* this is the socket() request */
    /* socket_request(SOCKET_ROOT,+domain,-socket_fd,-Error,_,_,_) 
       Currently only AF_INET domain */
    domain = (int)ptoc_int(CTXTc 2); 
    if (!translate_domain(domain, &domain)) {
      return FALSE;
    }
    
    sock_handle = socket(domain, SOCK_STREAM, IPPROTO_TCP);
	
    /* error handling */
    if (BAD_SOCKET(sock_handle)) {
      ecode = XSB_SOCKET_ERRORCODE;
      perror("SOCKET_REQUEST");
    } else {
      ecode = SOCK_OK;
    }

    ctop_int(CTXTc 3, (SOCKET) sock_handle);
	
    return set_error_code(CTXTc ecode, 4, "SOCKET_REQUEST");

  case SOCKET_BIND:
    /* socket_request(SOCKET_BIND,+domain,+sock_handle,+port,-Error,_,_) 
       Currently only supports AF_INET */
    sock_handle = (SOCKET) ptoc_int(CTXTc 3);
    portnum = (int)ptoc_int(CTXTc 4);
    domain = (int)ptoc_int(CTXTc 2);

    if (!translate_domain(domain, &domain)) {
      return FALSE;
    }
    
    /* Bind server to the agreed upon port number.
    ** See commdef.h for the actual port number. */
    FillWithZeros(socket_addr);
    socket_addr.sin_port = htons((unsigned short)portnum);
    socket_addr.sin_family = AF_INET;
#ifndef WIN_NT
    socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
    
    rc = bind(sock_handle, (PSOCKADDR) &socket_addr, sizeof(socket_addr));
	
    /* error handling */
    if (SOCKET_OP_FAILED(rc)) {
      ecode = XSB_SOCKET_ERRORCODE;
      perror("SOCKET_BIND");
    } else
      ecode = SOCK_OK;

    return set_error_code(CTXTc ecode, 5, "SOCKET_BIND");

  case SOCKET_LISTEN: 
    /* socket_request(SOCKET_LISTEN,+sock_handle,+length,-Error,_,_,_) */
    sock_handle = (SOCKET) ptoc_int(CTXTc 2);
    rc = listen(sock_handle, (int)ptoc_int(CTXTc 3));

    /* error handling */
    if (SOCKET_OP_FAILED(rc)) {
      ecode = XSB_SOCKET_ERRORCODE;
      perror("SOCKET_LISTEN");
    } else
      ecode = SOCK_OK;

    return set_error_code(CTXTc ecode, 4, "SOCKET_LISTEN");

  case SOCKET_ACCEPT:
    timeout_flag = socket_accept(CTXTc (SOCKET *)&rc, (int)pflags[SYS_TIMER]);
	  
    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND");
    } else {
      /* error handling */ 
      if (BAD_SOCKET(rc)) {
	ecode = XSB_SOCKET_ERRORCODE;
	perror("SOCKET_ACCEPT");
	sock_handle = rc; /* shut up warning */
      } else {
	sock_handle = rc; /* accept() returns sock_out */
	ecode = SOCK_OK;
      }
	       
      ctop_int(CTXTc 3, (SOCKET) sock_handle);
	       
      return set_error_code(CTXTc ecode,  4,  "SOCKET_ACCEPT");	  
    }
  case SOCKET_CONNECT: {
    /* socket_request(SOCKET_CONNECT,+domain,+sock_handle,+port,
       +hostname,-Error) */
    timeout_flag = socket_connect(CTXTc &rc, (int)pflags[SYS_TIMER]);

    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 6, "SOCKET_CONNECT");
    } else if (timeout_flag == TIMER_SETUP_ERR) {
      return set_error_code(CTXTc TIMER_SETUP_ERR, 6, "SOCKET_CONNECT");
    } else {
      /* error handling */
      if (SOCKET_OP_FAILED(rc)) {
	ecode = XSB_SOCKET_ERRORCODE;
	perror("SOCKET_CONNECT");
	/* close, because if connect() fails then socket becomes unusable */
	closesocket(ptoc_int(CTXTc 3));
      } else {
	ecode = SOCK_OK;
      }
      return set_error_code(CTXTc ecode,  6,  "SOCKET_CONNECT");
    }
  }

  case SOCKET_CLOSE: 
    /* socket_request(SOCKET_CLOSE,+sock_handle,-Error,_,_,_,_) */
    
    sock_handle = (SOCKET)ptoc_int(CTXTc 2);
    
    /* error handling */
    rc = closesocket(sock_handle);
    if (SOCKET_OP_FAILED(rc)) {
      ecode = XSB_SOCKET_ERRORCODE;
      perror("SOCKET_CLOSE");
    } else
      ecode = SOCK_OK;
    
    return set_error_code(CTXTc ecode, 3, "SOCKET_CLOSE");
    
  case SOCKET_RECV:
    /* socket_request(SOCKET_RECV,+Sockfd, -Msg, -Error,_,_,_) */
    // TODO: consider adding protection against interrupts, EINTR, like
    //       in socket_get0.
    timeout_flag = socket_recv(CTXTc &rc, &message_buffer, &msg_len, (int)pflags[SYS_TIMER]);
	  
    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND");
    } else {
      /* error handling */
      switch (rc) {
      case SOCK_OK:
	ecode = SOCK_OK;
	break;
      case SOCK_READMSG_FAILED:
	ecode = XSB_SOCKET_ERRORCODE;
	perror("SOCKET_RECV");
	break;
      case SOCK_READMSG_EOF:
	ecode = SOCK_EOF;
	break;
      case SOCK_HEADER_LEN_MISMATCH:
	ecode = XSB_SOCKET_ERRORCODE;
	break;
      default:
	xsb_abort("XSB bug: [SOCKET_RECV] invalid return code from readmsg");
      }
	       
      if (message_buffer != NULL) {
	/* use message_buffer+XSB_MSG_HEADER_LENGTH because the first
	   XSB_MSG_HEADER_LENGTH bytes are for the message length header */
	ctop_string(CTXTc 3, (char*)message_buffer+XSB_MSG_HEADER_LENGTH);
	mem_dealloc(message_buffer,msg_len,OTHER_SPACE);
      } else {  /* this happens at the end of a file */
	ctop_string(CTXTc 3, (char*)"");
      }
	       
      return set_error_code(CTXTc ecode, 4, "SOCKET_RECV");  
    }
	       
  case SOCKET_SEND:
    /* socket_request(SOCKET_SEND,+Sockfd, +Msg, -Error,_,_,_) */
    timeout_flag = socket_send(CTXTc &rc, (int)pflags[SYS_TIMER]);
    
    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND");
    } else {
      /* error handling */
      if (SOCKET_OP_FAILED(rc)) {
	ecode = XSB_SOCKET_ERRORCODE;
	perror("SOCKET_SEND");
      } else {
	ecode = SOCK_OK;
      }
      return set_error_code(CTXTc ecode,  4,  "SOCKET_SEND"); 
    }

  case SOCKET_GET0:
    /* socket_request(SOCKET_GET0,+Sockfd,-C,-Error,_,_,_) */
    message_buffer = &char_read;
    timeout_flag = socket_get0(CTXTc &rc, message_buffer, (int)pflags[SYS_TIMER]);
	  
    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND");
    } else {
      /*error handling */ 
      switch (rc) {
      case 1:
	ctop_int(CTXTc 3,(unsigned char)message_buffer[0]);
	ecode = SOCK_OK;
	break;
      case 0:
	ecode = SOCK_EOF;
	break;
      default:
	ctop_int(CTXTc 3,-1);
	perror("SOCKET_GET0");
	ecode = XSB_SOCKET_ERRORCODE;
      }
	       
      return set_error_code(CTXTc ecode,  4,  "SOCKET_GET0");
    }    
  case SOCKET_PUT:
    /* socket_request(SOCKET_PUT,+Sockfd,+C,-Error_,_,_) */
    timeout_flag = socket_put(CTXTc &rc, (int)pflags[SYS_TIMER]);
	       
    if (timeout_flag == TIMED_OUT) {
      return set_error_code(CTXTc TIMEOUT_ERR, 4, "SOCKET_SEND");
    } else {
      /* error handling */
      if (rc == 1) {
	ecode = SOCK_OK;
      } else if (SOCKET_OP_FAILED(rc)) {
	ecode = XSB_SOCKET_ERRORCODE;
	perror("SOCKET_PUT");
      }
	       
      return set_error_code(CTXTc ecode,  4,  "SOCKET_PUT");
    }
  case SOCKET_SET_OPTION: {
    /* socket_request(SOCKET_SET_OPTION,+Sockfd,+OptionName,+Value,_,_,_) */
    
    char *option_name = ptoc_string(CTXTc 3);
    
    sock_handle = (SOCKET)ptoc_int(CTXTc 2);

    /* Set the "linger" parameter to a small number of seconds */
    if (0==strcmp(option_name,"linger")) {
      int  linger_time=(int)ptoc_int(CTXTc 4);
      
      if (linger_time < 0) {
	sock_linger_opt.l_onoff = FALSE;
	sock_linger_opt.l_linger = 0;
      } else {
	sock_linger_opt.l_onoff = TRUE;
	sock_linger_opt.l_linger = linger_time;
      }
      
      if (SETSOCKOPT(sock_handle, SOL_SOCKET, SO_LINGER,
		     &sock_linger_opt, sizeof(sock_linger_opt))
	  < 0) {
	xsb_warn(CTXTc "[SOCKET_SET_OPTION] Cannot set socket linger time");
	return FALSE;
      } 
    }else {
      xsb_warn(CTXTc "[SOCKET_SET_OPTION] Invalid option, `%s'", option_name);
      return FALSE;
    }
    
    return TRUE;
  }

  case SOCKET_SET_SELECT:  {  
    /*socket_request(SOCKET_SET_SELECT,+connection_name,
      +R_sockfd,+W_sockfd,+E_sockfd) */
    prolog_term R_sockfd, W_sockfd, E_sockfd;
    int i, connection_count;
    int rmax_fd=0, wmax_fd=0, emax_fd=0; 
    char *connection_name = ptoc_string(CTXTc 2);
    
    /* bind fds to input arguments */
    R_sockfd = reg_term(CTXTc 3);
    W_sockfd = reg_term(CTXTc 4);
    E_sockfd = reg_term(CTXTc 5);	
    
    /* initialize the array of connect_t structure for select call */	
    init_connections(CTXT); 
    
    SYS_MUTEX_LOCK(MUTEX_SOCKETS);
    /* check whether the same connection name exists */
    for (i=0;i<MAXCONNECT;i++) {
      if ((connections[i].empty_flag==FALSE) &&
	  (strcmp(connection_name,connections[i].connection_name)==0)) 	
	xsb_abort("[SOCKET_SET_SELECT] Connection `%s' already exists!",
		  connection_name);
    }
    
    /* check whether there is empty slot left for connection */	
    if ((connection_count=checkslot())<MAXCONNECT) {
      if (connections[connection_count].connection_name == NULL) {
	connections[connection_count].connection_name = connection_name;
	connections[connection_count].empty_flag = FALSE;
	
	/* call the utility function separately to take the fds in */
	list_sockfd(R_sockfd, &connections[connection_count].readset,
		    &rmax_fd, &connections[connection_count].read_fds,
		    &connections[connection_count].sizer);
	list_sockfd(W_sockfd, &connections[connection_count].writeset,
		    &wmax_fd, &connections[connection_count].write_fds,
		    &connections[connection_count].sizew);
	list_sockfd(E_sockfd, &connections[connection_count].exceptionset, 
		    &emax_fd,&connections[connection_count].exception_fds,
		    &connections[connection_count].sizee);
	
	connections[connection_count].maximum_fd =
	  xsb_max(xsb_max(rmax_fd,wmax_fd), emax_fd);
      } else 
	/* if this one is reached, it is probably a bug */
	xsb_abort("[SOCKET_SET_SELECT] All connections are busy!");
    } else
      xsb_abort("[SOCKET_SET_SELECT] Max number of collections exceeded!");
    SYS_MUTEX_UNLOCK(MUTEX_SOCKETS);
    
    return TRUE;
  }
  
  case SOCKET_SELECT: {
    /* socket_request(SOCKET_SELECT,+connection_name, +timeout
       -avail_rsockfds,-avail_wsockfds,
       -avail_esockfds,-ecode)
       Returns 3 prolog_terms for available socket fds */

    prolog_term Avail_rsockfds, Avail_wsockfds, Avail_esockfds;
    prolog_term Avail_rsockfds_tail, Avail_wsockfds_tail, Avail_esockfds_tail;

    int maxfd;
    int i;       /* index for connection_count */
    char *connection_name = ptoc_string(CTXTc 2);
    struct timeval *tv;
    prolog_term timeout_term;
    int timeout =0;
    int connectname_found = FALSE;
    int count=0;			

    SYS_MUTEX_LOCK(MUTEX_SOCKETS);
    /* specify the time out */
    timeout_term = reg_term(CTXTc 3);
    if (isointeger(timeout_term)) {
      timeout = (int)oint_val(timeout_term);
      /* initialize tv */
      tv = (struct timeval *)mem_alloc(sizeof(struct timeval),LEAK_SPACE);
      tv->tv_sec = timeout;
      tv->tv_usec = 0;
    } else
      tv = NULL; /* no timeouts */

    /* initialize the prolog term */ 
    Avail_rsockfds = p2p_new(CTXT);
    Avail_wsockfds = p2p_new(CTXT);
    Avail_esockfds = p2p_new(CTXT); 

    /* bind to output arguments */
    Avail_rsockfds = reg_term(CTXTc 4);
    Avail_wsockfds = reg_term(CTXTc 5);
    Avail_esockfds = reg_term(CTXTc 6);

    Avail_rsockfds_tail = Avail_rsockfds;
    Avail_wsockfds_tail = Avail_wsockfds;
    Avail_esockfds_tail = Avail_esockfds;

    /*
      // This was wrong. Lists are now made inside test_ready()
      c2p_list(CTXTc Avail_rsockfds_tail);
      c2p_list(CTXTc Avail_wsockfds_tail);	
      c2p_list(CTXTc Avail_esockfds_tail); 
    */
    
    for (i=0; i < MAXCONNECT; i++) {
      /* find the matching connection_name to select */
      if(connections[i].empty_flag==FALSE) {
	if (strcmp(connection_name, connections[i].connection_name) == 0) {
	  connectname_found = TRUE;
	  count = i;
	  break;
	} 
      }
    }
    if( i >= MAXCONNECT )  /* if no matching connection_name */
      xsb_abort("[SOCKET_SELECT] connection `%s' doesn't exist",
		connection_name); 
    
    /* compute maxfd for select call */
    maxfd = connections[count].maximum_fd + 1;

    /* FD_SET all sockets */
    set_sockfd( CTXTc count );

    /* test whether the socket fd is available */
    rc = select(maxfd, &connections[count].readset, 
		&connections[count].writeset,
		&connections[count].exceptionset, tv);
    
    /* error handling */	
    if (rc == 0)     /* timed out */
      ecode = TIMEOUT_ERR;
    else if (SOCKET_OP_FAILED(rc)) {
      perror("SOCKET_SELECT");
      ecode = XSB_SOCKET_ERRORCODE;
    } else {      /* no error */
      ecode = SOCK_OK;
	 
      /* call the utility function to return the available socket fds */
      test_ready(CTXTc &Avail_rsockfds_tail, &connections[count].readset,
		 connections[count].read_fds,connections[count].sizer);

      test_ready(CTXTc &Avail_wsockfds_tail, &connections[count].writeset,
		 connections[count].write_fds,connections[count].sizew);

      test_ready(CTXTc &Avail_esockfds_tail,&connections[count].exceptionset,
		 connections[count].exception_fds,connections[count].sizee);
    }
    SYS_MUTEX_UNLOCK(MUTEX_SOCKETS);

    if (tv) mem_dealloc((struct timeval *)tv,sizeof(struct timeval),LEAK_SPACE);
    SQUASH_LINUX_COMPILER_WARN(connectname_found) ; 
    return set_error_code(CTXTc ecode, 7, "SOCKET_SELECT");
  }

  case SOCKET_SELECT_DESTROY:  { 
    /*socket_request(SOCKET_SELECT_DESTROY, +connection_name) */
    char *connection_name = ptoc_string(CTXTc 2);
    select_destroy(CTXTc connection_name);
    return TRUE;
  }

  default:
    xsb_warn(CTXTc "[SOCKET_REQUEST] Invalid socket request %d", (int) ptoc_int(CTXTc 1));
    return FALSE;
  }

  /* This trick would report a bug, if a newly added case
     doesn't have a return clause */
  xsb_bug("SOCKET_REQUEST case %d has no return clause", ptoc_int(CTXTc 1));
}
Ejemplo n.º 9
0
void print_detailed_tablespace_stats(CTXTdecl) {

  NodeStats
    abtn,		/* Asserted Basic Trie Nodes */
    btn,		/* Basic Trie Nodes */
    aln,		/* Answer List Nodes */
    varsf,		/* Variant Subgoal Frames */
    asi;		/* Answer Subgoal Information */

  HashStats
    abtht,		/* Asserted Basic Trie Hash Tables */
    btht;		/* Basic Trie Hash Tables */

  NodeStats  
    pri_tstn,		/* Private Time Stamp Trie Nodes */
    pri_tsi,		/* Private Time Stamp Indices (Index Entries/Nodes) */
    pri_prodsf,		/* Private Subsumptive Producer Subgoal Frames */
    pri_conssf,		/* Private Subsumptive Consumer Subgoal Frames */
    pri_btn,		/* Private Basic Trie Nodes (Tables) */
    pri_assert_btn,	/* Private Basic Trie Nodes (Asserts) */
    pri_aln,		/* Private Answer List Nodes */
    pri_varsf,		/* Private Variant Subgoal Frames */
    pri_asi;		/* Private Answer Subgoal Information */
  
  HashStats
    pri_btht,		/* Private Basic Trie Hash Tables (Tables) */
    pri_assert_btht,	/* Private Basic Trie Hash Tables (Asserts) */
    pri_tstht;		/* Private Time Stamp Trie Hash Tables */

  size_t
    tablespace_alloc, tablespace_used,
    pri_tablespace_alloc, pri_tablespace_used,
    shared_tablespace_alloc, shared_tablespace_used,
    trieassert_alloc, trieassert_used,
    de_space_alloc, de_space_used,
    dl_space_alloc, dl_space_used,
    pnde_space_alloc, pnde_space_used,
    pri_de_space_alloc, pri_de_space_used,
    pri_dl_space_alloc, pri_dl_space_used,
    pri_pnde_space_alloc, pri_pnde_space_used;

  size_t num_de_blocks, num_dl_blocks, num_pnde_blocks;
  size_t pri_num_de_blocks, pri_num_dl_blocks, pri_num_pnde_blocks;

  SM_Lock(smTableBTN);
  btn = node_statistics(&smTableBTN);
  SM_Unlock(smTableBTN);
  SM_Lock(smTableBTHT);
  btht = hash_statistics(CTXTc &smTableBTHT);
  SM_Unlock(smTableBTHT);
  SM_Lock(smVarSF);
  varsf = subgoal_statistics(CTXTc &smVarSF);
  SM_Unlock(smVarSF);
  SM_Lock(smALN);
  aln = node_statistics(&smALN);
  SM_Unlock(smALN);
  SM_Lock(smASI);
  asi = node_statistics(&smASI);
  SM_Unlock(smASI);

  SYS_MUTEX_LOCK( MUTEX_DELAY );			
  de_space_alloc = allocated_de_space(current_de_block_gl,&num_de_blocks);
  de_space_used = de_space_alloc - unused_de_space();
  dl_space_alloc = allocated_dl_space(current_dl_block_gl,&num_dl_blocks);
  dl_space_used = dl_space_alloc - unused_dl_space();
  pnde_space_alloc = allocated_pnde_space(current_pnde_block_gl,&num_pnde_blocks);
  pnde_space_used = pnde_space_alloc - unused_pnde_space();
  SYS_MUTEX_UNLOCK( MUTEX_DELAY );			

  pri_btn = node_statistics(private_smTableBTN);
  pri_btht = hash_statistics(CTXTc private_smTableBTHT);
  pri_assert_btn = node_statistics(private_smAssertBTN);
  pri_assert_btht = hash_statistics(CTXTc private_smAssertBTHT);
  pri_aln = node_statistics(private_smALN);
  pri_asi = node_statistics(private_smASI);
  pri_varsf = subgoal_statistics(CTXTc private_smVarSF);
  pri_prodsf = subgoal_statistics(CTXTc private_smProdSF);
  pri_conssf = subgoal_statistics(CTXTc private_smConsSF);
  pri_tstn = node_statistics(private_smTSTN);
  pri_tsi = node_statistics(private_smTSIN);
  pri_btht = hash_statistics(CTXTc private_smTableBTHT);
  pri_tstht = hash_statistics(CTXTc private_smTSTHT);

  pri_de_space_alloc = allocated_de_space(private_current_de_block,&pri_num_de_blocks);
  pri_de_space_used = pri_de_space_alloc - unused_de_space_private(CTXT);
  pri_dl_space_alloc = allocated_dl_space(private_current_dl_block,&pri_num_dl_blocks);
  pri_dl_space_used = pri_dl_space_alloc - unused_dl_space_private(CTXT);
  pri_pnde_space_alloc = allocated_pnde_space(private_current_pnde_block,&pri_num_pnde_blocks);
  pri_pnde_space_used = pri_pnde_space_alloc - unused_pnde_space_private(CTXT);

  pri_tablespace_alloc = CurrentPrivateTableSpaceAlloc(pri_btn,pri_btht,pri_varsf,pri_prodsf,
						       pri_conssf,pri_aln,pri_tstn,pri_tstht,pri_tsi,
						       pri_asi);
  pri_tablespace_used = CurrentPrivateTableSpaceUsed(pri_btn,pri_btht,pri_varsf,pri_prodsf,
						     pri_conssf,pri_aln,pri_tstn,pri_tstht,pri_tsi,
						     pri_asi);

  pri_tablespace_alloc = pri_tablespace_alloc + pri_de_space_alloc + 
    pri_dl_space_alloc + pri_pnde_space_alloc;
  pri_tablespace_used = pri_tablespace_used + pri_de_space_used + pri_dl_space_used + pri_pnde_space_used;

  shared_tablespace_alloc = CurrentSharedTableSpaceAlloc(btn,btht,varsf,aln,asi);
  shared_tablespace_used = CurrentSharedTableSpaceUsed(btn,btht,varsf,aln,asi);

  shared_tablespace_alloc = shared_tablespace_alloc + de_space_alloc + dl_space_alloc + pnde_space_alloc;
  shared_tablespace_used = shared_tablespace_used + de_space_used + dl_space_used + pnde_space_used;

  tablespace_alloc = shared_tablespace_alloc + pri_tablespace_alloc;
  tablespace_used =  shared_tablespace_used + pri_tablespace_used;

  abtn = node_statistics(&smAssertBTN);
  abtht = hash_statistics(CTXTc &smAssertBTHT);
  trieassert_alloc = NodeStats_SizeAllocNodes(abtn) + HashStats_SizeAllocTotal(abtht);
  trieassert_used = NodeStats_SizeUsedNodes(abtn) + HashStats_SizeUsedTotal(abtht);
  SQUASH_LINUX_COMPILER_WARN(trieassert_used) ; 

  printf("  Current Total Allocation:   %12"UIntfmt" bytes\n"
  	 "  Current Total Usage:        %12"UIntfmt" bytes\n",
	 pspacesize[TABLE_SPACE]-trieassert_alloc,  
	 pspacesize[TABLE_SPACE]-trieassert_alloc-(tablespace_alloc-tablespace_used));

  //   printf("\n --------------------- Shared tables ---------------------\n");

  printf("\n"
	 "Shared Table Space Usage (exc"UIntfmt"ding asserted and interned tries) \n");
  printf("  Current Total Allocation:   %12"UIntfmt" bytes\n"
  	 "  Current Total Usage:        %12"UIntfmt" bytes\n",
	 shared_tablespace_alloc,shared_tablespace_used);

  // Basic Trie Stuff
  if ( NodeStats_NumBlocks(btn) > 0 || HashStats_NumBlocks(btht) > 0 || NodeStats_NumBlocks(aln) > 0) {
    printf("\n"
	   "  Basic Tries\n");
    if ( NodeStats_NumBlocks(btn) > 0) 
      print_NodeStats(btn,"Basic Trie Nodes");
    if (HashStats_NumBlocks(btht) > 0)
      print_HashStats(btht,"Basic Trie Hash Tables");
    if ( NodeStats_NumBlocks(aln) > 0) 
      print_NodeStats(aln,"Answer List Nodes (for Incomplete Variant Tables)");
  }

  // Subgoal Frames
  if (NodeStats_NumBlocks(varsf) > 0) {
    printf("\n"
	   "  Subgoal Frames\n");
    if (NodeStats_NumBlocks(varsf) > 0)
      print_NodeStats(varsf,"Variant Subgoal Frames");
  }

  // Conditional Answers
  if (dl_space_alloc > 0 || de_space_alloc > 0 || pnde_space_alloc > 0 
      || NodeStats_NumBlocks(asi) > 0) {
    printf("\n"
	   "  Information for Conditional Answers in Variant Tables \n");
    if (dl_space_alloc > 0) 
      print_wfs_usage(dl_space_alloc,dl_space_used,num_dl_blocks,DLS_PER_BLOCK,
		      sizeof(struct delay_list),"Delay Lists");
    if (de_space_alloc > 0) 
      print_wfs_usage(de_space_alloc,de_space_used,num_de_blocks,DES_PER_BLOCK,
		      sizeof(struct delay_element),"Delay Elements");
    if (pnde_space_alloc > 0) 
      print_wfs_usage(pnde_space_alloc,pnde_space_used,num_pnde_blocks,PNDES_PER_BLOCK,
		      sizeof(struct pos_neg_de_list),"Back-pointer Lists");
    if ( NodeStats_NumBlocks(asi) > 0)
      print_NodeStats(asi,"Answer Substitution Frames");
  }

  // Private trie assert space
  if ( NodeStats_NumBlocks(abtn) > 0 || HashStats_NumBlocks(abtht) > 0) {
  printf("\n ---------------- Shared Asserted and Interned Tries  ----------------\n");
    if ( NodeStats_NumBlocks(abtn) > 0) 
      print_NodeStats(abtn,"Basic Trie Nodes (Assert)");
    if (HashStats_NumBlocks(abtht) > 0)
      print_HashStats(abtht,"Basic Trie Hash Tables (Assert)");
  }

  printf("\n --------------------- Private tables ---------------------\n");
  printf("\n"
	 "Private Table Space Usage for Thread %"Intfmt" (exc"UIntfmt"ding asserted and interned tries) \n"
	 "  Current Total Allocation:   %12"UIntfmt" bytes\n"
  	 "  Current Total Usage:        %12"UIntfmt" bytes\n",
	 xsb_thread_id,pri_tablespace_alloc,pri_tablespace_used);

  // Basic Trie Stuff
  if ( NodeStats_NumBlocks(pri_btn) > 0 || HashStats_NumBlocks(pri_btht) > 0 
       || NodeStats_NumBlocks(pri_aln) > 0) {
    printf("\n"
	   "  Basic Tries\n");
    if ( NodeStats_NumBlocks(pri_btn) > 0) 
      print_NodeStats(pri_btn,"Basic Trie Nodes");
    if (HashStats_NumBlocks(pri_btht) > 0)
      print_HashStats(pri_btht,"Basic Trie Hash Tables");
    if ( NodeStats_NumBlocks(pri_aln) > 0) 
      print_NodeStats(pri_aln,"Answer List Nodes (for Incomplete Variant Tables)");
  }

  // Subgoal Frames
  if (NodeStats_NumBlocks(pri_varsf) > 0 || NodeStats_NumBlocks(pri_prodsf) > 0 ||
      NodeStats_NumBlocks(pri_conssf) > 0) {
    printf("\n"
	   "  Subgoal Frames\n");
    if (NodeStats_NumBlocks(pri_varsf) > 0)
      print_NodeStats(pri_varsf,"Variant Subgoal Frames");
    if (NodeStats_NumBlocks(pri_prodsf) > 0)
      print_NodeStats(pri_prodsf,"Producer Subgoal Frames");
    if (NodeStats_NumBlocks(pri_conssf) > 0)
      print_NodeStats(pri_conssf,"Consumer Subgoal Frames");
  }

  // Subsumptive Tables
  if ( NodeStats_NumBlocks(pri_tstn) > 0 || HashStats_NumBlocks(pri_tstht) > 0
       || NodeStats_NumBlocks(pri_tsi) > 0) {
    printf("\n"
	   "  Time Stamp Tries (for Subsumptive Tables) \n");
    if (NodeStats_NumBlocks(pri_tstn) > 0) 
      print_NodeStats(pri_tstn,"Time Stamp Trie Nodes");
    if (HashStats_NumBlocks(pri_tstht) > 0) 
      print_HashStats(pri_tstht,"Time Stamp Trie Hash Tables");
    if (NodeStats_NumBlocks(pri_tsi) > 0) 
      print_NodeStats(pri_tsi,"Time Stamp Trie Index Nodes");
  }

  // Conditional Answers
  if (pri_dl_space_alloc > 0 || pri_de_space_alloc > 0 || pri_pnde_space_alloc > 0 
      || NodeStats_NumBlocks(pri_asi) > 0) {
    printf("\n"
	   "  Information for Conditional Answers in Variant Tables \n");
    if (pri_dl_space_alloc > 0) 
      print_wfs_usage(pri_dl_space_alloc,pri_dl_space_used,pri_num_dl_blocks,DLS_PER_BLOCK,
		      sizeof(struct delay_list),"Delay Lists");
    if (pri_de_space_alloc > 0) 
      print_wfs_usage(pri_de_space_alloc,pri_de_space_used,pri_num_de_blocks,DES_PER_BLOCK,
		      sizeof(struct delay_element),"Delay Elements");
    if (pri_pnde_space_alloc > 0) 
      print_wfs_usage(pri_pnde_space_alloc,pri_pnde_space_used,pri_num_pnde_blocks,PNDES_PER_BLOCK,
		      sizeof(struct pos_neg_de_list),"Back-pointer Lists");
    if ( NodeStats_NumBlocks(pri_asi) > 0)
      print_NodeStats(pri_asi,"Answer Substitution Frames");
  }

  // Private trie assert space
  if ( NodeStats_NumBlocks(pri_assert_btn) > 0 || HashStats_NumBlocks(pri_assert_btht) > 0) {
  printf("\n ---------------- Private Asserted and Interned Tries  ----------------\n");
    if ( NodeStats_NumBlocks(pri_assert_btn) > 0) 
      print_NodeStats(pri_assert_btn,"Basic Trie Nodes (Assert)");
    if (HashStats_NumBlocks(pri_assert_btht) > 0)
      print_HashStats(pri_assert_btht,"Basic Trie Hash Tables (Assert)");
  }

  printf("\n");
}