thread_xsb.c

00001 /* File:      thread_xsb.c
00002 ** Author(s): Marques
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 */
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include <math.h>
00027 
00028 #include "xsb_debug.h"
00029 #include "xsb_config.h"
00030 
00031 #include "basictypes.h"
00032 #include "basicdefs.h"
00033 
00034 #include "cell_xsb.h"
00035 #include "register.h"
00036 #include "context.h"
00037 #include "cinterf.h"
00038 #include "error_xsb.h"
00039 
00040 #ifndef SYSTEM_FLAGS
00041 #include "flags_xsb.h"
00042 #endif
00043 
00044 #include "flag_defs_xsb.h"
00045 #include "deref.h"
00046 #include "ptoc_tag_xsb_i.h"
00047 #include "thread_xsb.h"
00048 #include "rw_lock.h"
00049 #include "memory_xsb.h"
00050 #include "sig_xsb.h"
00051 
00052 #ifdef MULTI_THREAD
00053 
00054 /* different things are included based on context.h -- easiest to
00055    include this conditionally. */
00056 #include "macro_xsb.h"
00057 
00058 #include <errno.h>
00059 
00060 int emuloop(CTXTdeclc byte *startaddr);
00061 void cleanup_thread_structures(CTXTdecl);
00062 void init_machine(CTXTdeclc int, int, int, int);
00063 void set_init_glstack_size(int);
00064 void set_init_tcpstack_size(int);
00065 void set_init_pdl_size(int);
00066 void set_init_complstack_size(int);
00067 Cell copy_term_from_thread( th_context *th, th_context *from, Cell arg1 );
00068 extern pthread_attr_t detached_attr_gl;
00069 
00070 typedef struct
00071 {       
00072         pthread_t       tid;
00073 #ifdef WIN_NT
00074         pthread_t *     tid_addr;
00075 #endif
00076         int             valid;
00077         int             detached ;
00078         th_context *    ctxt ;
00079 } xsb_thread_t ;
00080 
00081 static xsb_thread_t th_vec[MAX_THREADS];
00082 static xsb_thread_t *th_next = th_vec;
00083 
00084 extern void release_private_dynamic_resources(CTXTdecl);
00085 extern void release_private_tabling_resources(CTXTdecl);
00086 
00087 //extern void thread_free_dyn_blks(CTXTdecl);
00088 //extern void thread_free_tab_blks(CTXTdecl);
00089 extern void delete_predicate_table(CTXTdeclc TIFptr);
00090 
00091 MutexFrame sys_mut[MAX_SYS_MUTEXES] ;
00092 
00093 pthread_mutex_t th_mutex = PTHREAD_MUTEX_INITIALIZER;
00094 
00095 pthread_mutex_t completing_mut;
00096 pthread_cond_t completing_cond;
00097 
00098 // pthread_t is a pointer in Unix, structure in Windows libraries
00099 #ifdef WIN_NT
00100 #define P_PTHREAD_T_P &tid
00101 #define P_PTHREAD_T *tid
00102 #else
00103 #define P_PTHREAD_T_P tid
00104 #define P_PTHREAD_T tid
00105 #endif
00106 
00107 char *mutex_names[] = {
00108 "mutex_dynamic","mutex_io","mutex_table","mutex_trie","mutex_symbol",
00109 "mutex_flags"," mutex_load_undef","mutex_delay","mutex_sys_system","unused",
00110 "unused","unused","unused","unused","unused",
00111 "mutex_string","mutex_atom_buf","mutex_sm","mutex_stacks","mutex_sockets",
00112 "mutex_mem","mutex_odbc","mutex_gentag","mutex_dispbkhdr","unused",
00113 "unused","unused","unused","unused","unused",
00114 "mutex_console","mutex_user1","mutex_user2","mutex_user3","mutex_user4",
00115 "mutex_user5","mutex_user6","mutex_user7","mutex_user9","mutex_user9"};
00116 
00117 void print_mutex_use() {
00118   int i;
00119 
00120   printf("Mutexes used since last statistics:\n");
00121   for (i = 0; i < MAX_SYS_MUTEXES; i++) {
00122     if (sys_mut[i].num_locks > 0) 
00123       printf("Mutex %s (%d): %d\n",mutex_names[i],i,sys_mut[i].num_locks);
00124   }
00125   for (i = 0; i < MAX_SYS_MUTEXES; i++) {
00126     sys_mut[i].num_locks = 0;
00127   }
00128 }
00129 
00130 
00131 /*
00132 static void show_policy(void) {
00133   int my_policy;
00134   struct sched_param my_param;
00135   int status, min_priority, max_priority;
00136 
00137   if ((status = pthread_getschedparam(pthread_self(),&my_policy,&my_param))) {
00138     xsb_abort("bad scheduling status");
00139   }
00140   printf("thread routine running at %s/%d\n",
00141          (my_policy == SCHED_FIFO ? "FIFO" 
00142           : (my_policy == SCHED_RR ? "RR"
00143              : (my_policy == SCHED_OTHER ? "OTHER"
00144                 : "unknown") )),my_param.sched_priority);
00145 
00146   printf("min %d max %d\n",sched_get_priority_min(my_policy),
00147          sched_get_priority_max(my_policy));
00148   
00149 }
00150 */
00151 
00152 /* finds thread in the thread-vector, returning its index if found, -1
00153    otherwise */
00154 static int th_find( pthread_t_p tid )
00155 {
00156         xsb_thread_t *pos;
00157 
00158         for( pos = th_vec ; pos < th_next ; pos++ )
00159           if( pos->valid && pthread_equal( P_PTHREAD_T, pos->tid ) )
00160                         return pos - th_vec ;
00161         return -1 ;
00162 }
00163 
00164 /* On normal termination, returns xsb_thread_id for a (usu. newly
00165    created) thread */
00166 static int th_new( pthread_t_p t, th_context *ctxt )
00167 {
00168         xsb_thread_t *pos ;
00169         int i ;
00170         if( (i = th_find(t)) != -1 )
00171                 return i ;
00172         for( pos = th_vec ; pos < th_vec + MAX_THREADS ; pos++ )
00173                 if( !pos->valid ) 
00174                         break;
00175 
00176         if( pos - th_vec >= MAX_THREADS )
00177                 xsb_abort("[THREAD] Too many threads");
00178         else if( pos == th_next )
00179                 th_next++ ;
00180 
00181         pos->ctxt = ctxt ;
00182         pos->valid = 1;
00183 #ifdef WIN_NT
00184         pos->tid = *t;
00185         pos->tid_addr = t;
00186 #else
00187         pos->tid = t;
00188 #endif
00189         pos->detached = 0;
00190         return pos - th_vec ;
00191 }
00192 
00193 static pthread_t_p th_get( int i )
00194 {
00195         if( th_vec[i].valid )
00196 #ifdef WIN_NT
00197           return th_vec[i].tid_addr;
00198 #else
00199           return th_vec[i].tid ;
00200 #endif
00201         else
00202           return (pthread_t_p)0 ;
00203 }
00204 
00205 static void th_delete( int i )
00206 {
00207 #ifdef WIN_NT
00208         mem_dealloc(th_vec[i].tid_addr,sizeof(pthread_t),THREAD_SPACE);
00209 #endif  
00210         th_vec[i].valid = 0;
00211 }
00212 
00213 void init_system_threads( th_context *ctxt )
00214 {
00215   pthread_t tid = pthread_self();
00216   th_new(P_PTHREAD_T_P, ctxt) ;
00217 }
00218 
00219 void init_system_mutexes( void )
00220 {
00221         int i ;
00222         pthread_mutexattr_t attr_rec ;
00223         pthread_mutexattr_t attr_std ;
00224 
00225 /* make system mutex recursive, for there are recursive prolog calls    */
00226 /* to stuff that must be executed in mutual exclusion                   */
00227 
00228         pthread_mutexattr_init( &attr_rec ) ;
00229         if( pthread_mutexattr_settype( &attr_rec, PTHREAD_MUTEX_RECURSIVE_NP )<0 )
00230                 xsb_abort( "[THREAD] Error initializing mutexes" ) ;
00231 
00232         pthread_mutexattr_init( &attr_std ) ;
00233 
00234         for( i = 0; i <=  LAST_REC_MUTEX ; i++ ) {
00235           pthread_mutex_init( MUTARRAY_MUTEX(i), &attr_rec ) ;
00236           MUTARRAY_OWNER(i) = -1;
00237         }
00238         for( i = LAST_REC_MUTEX + 1 ; i < MAX_SYS_MUTEXES ; i++ ) {
00239           pthread_mutex_init( MUTARRAY_MUTEX(i), &attr_std ) ;
00240           MUTARRAY_OWNER(i) = -1;
00241         }
00242 
00243 #ifdef MULTI_THREAD_RWL
00244         rw_lock_init(&trie_rw_lock);
00245 #endif
00246 
00247         pthread_mutex_init( &completing_mut, &attr_std );
00248         pthread_cond_init( &completing_cond, NULL );
00249 }
00250 
00251 /* calls _$thread_run/1 in thread.P */
00252 static void *xsb_thread_run( void *arg )
00253 {
00254         pthread_t tid;
00255         th_context *ctxt = (th_context *)arg ;
00256 
00257         pthread_mutex_lock( &th_mutex );
00258         tid = pthread_self();
00259 /* if the xsb thread id was just created we need to re-initialize it on the
00260    thread context */
00261         ctxt->tid = th_new( P_PTHREAD_T_P, ctxt ) ;
00262         pthread_mutex_unlock( &th_mutex );
00263         emuloop( ctxt, get_ep((Psc)flags[THREAD_RUN]) ) ;
00264 
00265         /* execution shouldn't arrive here */
00266         xsb_bug( "emuloop returned from thread" );
00267 
00268         return NULL ;
00269 }
00270 
00271 static void copy_pflags( th_context *to, th_context *from )
00272 {
00273         int i ;
00274 
00275         for( i = 0; i < MAX_PRIVATE_FLAGS; i++ )
00276                 to->_pflags[i] = from->_pflags[i] ;
00277 }
00278 
00279 static int xsb_thread_create(th_context *th)
00280 {
00281   int rc, is_detached ;
00282   Cell goal ;
00283   th_context *new_th_ctxt ;
00284   pthread_t_p thr ;
00285   Integer id ;
00286        
00287   goal = ptoc_tag(th, 2) ;
00288   new_th_ctxt = mem_alloc(sizeof(th_context),THREAD_SPACE) ;
00289 
00290   copy_pflags(new_th_ctxt, th) ;
00291   init_machine(new_th_ctxt,ptoc_int(CTXTc 4),ptoc_int(CTXTc 5),
00292                ptoc_int(CTXTc 6),ptoc_int(CTXTc 7)) ;
00293   new_th_ctxt->_reg[1] = copy_term_from_thread(new_th_ctxt, th, goal) ;
00294 
00295   flags[NUM_THREADS]++ ;
00296 
00297   is_detached = ptoc_int(CTXTc 8);
00298 
00299 #ifdef WIN_NT
00300   thr = mem_alloc(sizeof(pthread_t),THREAD_SPACE);
00301   if (is_detached) { /* set detached */
00302     rc = pthread_create(thr, &detached_attr_gl, &xsb_thread_run, 
00303                          (void *)new_th_ctxt ) ;
00304   }
00305   else {
00306     rc = pthread_create(thr, NULL, &xsb_thread_run, (void *)new_th_ctxt ) ;
00307   }
00308 
00309 #else
00310 
00311   if (is_detached) { /* set detached */
00312     rc = pthread_create( &thr, &detached_attr_gl, &xsb_thread_run, 
00313                          (void *)new_th_ctxt ) ;
00314   }
00315   else {
00316     rc = pthread_create( &thr, NULL, &xsb_thread_run, (void *)new_th_ctxt ) ;
00317   }
00318 
00319 #endif
00320 
00321   if (rc == EAGAIN) {
00322     xsb_resource_error(th,"system threads","xsb_thread_create",2);
00323   } else {
00324     if (rc != 0) 
00325       xsb_abort("Failure to create thread: error %d\n",rc);
00326   }
00327 
00328 /* This repetition of the call to th_new is need for concurrency reasons */
00329   pthread_mutex_lock( &th_mutex );
00330   id = th_new( thr, new_th_ctxt ) ;
00331 
00332   if (is_detached) th_vec[id].detached = 1;
00333 
00334   pthread_mutex_unlock( &th_mutex );
00335 
00336   ctop_int( th, 3, id ) ;
00337   return rc ;
00338 }
00339 
00340 th_context *find_context( int id )
00341 {
00342         if (th_vec[id].valid)
00343                 return th_vec[id].ctxt;
00344         else
00345                 return NULL;
00346 }
00347 
00348 void release_held_mutexes(CTXTdecl) {
00349   int i;
00350 
00351   //  printf("releasing held mutexes\n");
00352   for( i = 0; i <=  LAST_REC_MUTEX ; i++ ) {
00353     if ( MUTARRAY_OWNER(i) == xsb_thread_id) {
00354       pthread_mutex_unlock( MUTARRAY_MUTEX(i)) ;
00355     }
00356   }
00357   for( i = LAST_REC_MUTEX + 1 ; i < MAX_SYS_MUTEXES ; i++ ) {
00358     if ( MUTARRAY_OWNER(i) == xsb_thread_id) {
00359       pthread_mutex_unlock( MUTARRAY_MUTEX(i)) ;
00360     }
00361     pthread_mutex_unlock( MUTARRAY_MUTEX(i)) ;
00362   }
00363 }
00364 #else /* Not MULTI_THREAD */
00365 
00366 void print_mutex_use() {
00367   xsb_abort("This engine is not configured for mutex profiling.");
00368 }
00369 
00370 #endif /* MULTI_THREAD */
00371 
00372 int xsb_thread_self()
00373 {
00374 #ifdef MULTI_THREAD
00375         int id;
00376         pthread_t tid = pthread_self();
00377 
00378         pthread_mutex_lock( &th_mutex );
00379         id = th_find( P_PTHREAD_T_P ) ;
00380         pthread_mutex_unlock( &th_mutex );
00381         return id;
00382 #else
00383         return 0;
00384 #endif
00385 }
00386 
00387 extern void release_private_tabling_resources(CTXTdecl);
00388 extern void abolish_private_tables(CTXTdecl);
00389 extern void abolish_shared_tables(CTXTdecl);
00390 
00391 xsbBool xsb_thread_request( CTXTdecl ) 
00392 {
00393         Integer request_num = ptoc_int(CTXTc 1) ;
00394 #ifdef MULTI_THREAD
00395         Integer id, rval;
00396         pthread_t_p tid ;
00397         pthread_t tid2;
00398         int i;
00399         Integer rc ;
00400         xsbBool success = TRUE ;
00401 
00402         switch( request_num )
00403         {
00404         case XSB_THREAD_CREATE:
00405           rc = xsb_thread_create(th) ;
00406           break ;
00407 
00408           /* TLS: replaced thread_free_tab_blks() by
00409              thread_free_private_tabling_resources, which sets
00410              appropriate tifs to 0, but doesn't use
00411              delete_predicate_table -- rather it deallocates the
00412              structure managers directly.  */
00413 
00414         case XSB_THREAD_EXIT:
00415           rval = ptoc_int(CTXTc 2 ) ;
00416           release_held_mutexes(CTXT);
00417           release_private_tabling_resources(CTXT);
00418           release_private_dynamic_resources(CTXT);
00419           cleanup_thread_structures(CTXT) ;
00420           mem_dealloc(th,sizeof(th_context),THREAD_SPACE) ;
00421           flags[NUM_THREADS]-- ;
00422           pthread_mutex_lock( &th_mutex );
00423           tid2 = pthread_self();
00424 #ifdef WIN_NT
00425           i = th_find( &tid2 ) ;
00426 #else
00427           i = th_find( tid2 ) ;
00428 #endif
00429           if( th_vec[i].detached )
00430             th_delete(i);
00431           pthread_mutex_unlock( &th_mutex );
00432           pthread_exit((void *) rval ) ;
00433           rc = 0 ; /* keep compiler happy */
00434           break ;
00435 
00436         case XSB_THREAD_JOIN: {
00437           id = ptoc_int( CTXTc 2 ) ;
00438           pthread_mutex_lock( &th_mutex );
00439           tid = th_get( id ) ;
00440           pthread_mutex_unlock( &th_mutex );
00441           if( tid == (pthread_t_p)0 )
00442             xsb_existence_error(CTXTc "thread",reg[2],"xsb_thread_join",1,1); 
00443           rc = pthread_join(P_PTHREAD_T, (void **)&rval ) ;
00444           if (rc != 0) {
00445             if (rc == EINVAL) { /* pthread found, but not joinable */
00446               xsb_permission_error(CTXTc "thread_join","non-joinable thread",
00447                                    reg[2],"xsb_thread_join",1); 
00448             } else {
00449               if (rc == ESRCH)  { /* no such pthread found */
00450                 xsb_existence_error(CTXTc "thread",reg[2],
00451                                     "xsb_thread_join",1,1); 
00452               }
00453             }
00454           }
00455 
00456           pthread_mutex_lock( &th_mutex );
00457           th_delete(id);
00458           pthread_mutex_unlock( &th_mutex );
00459           ctop_int( CTXTc 3, rval ) ;
00460           break ;
00461         }
00462 
00463         case XSB_THREAD_DETACH:
00464           id = ptoc_int( CTXTc 2 ) ;
00465           pthread_mutex_lock( &th_mutex );
00466           tid = th_get( id ) ;
00467           if( tid == (pthread_t_p)0 )
00468             xsb_abort( "[THREAD] Thread detach - invalid thread id" );
00469           pthread_mutex_unlock( &th_mutex );
00470           rc = PTHREAD_DETACH( tid ) ;
00471           if (rc == EINVAL) { /* pthread found, but not joinable */
00472             xsb_permission_error(CTXTc "thread_detach","non-joinable thread",
00473                                  reg[2],"xsb_thread_detach",1); 
00474           } else {
00475             if (rc == ESRCH)  { /* no such pthread found */
00476               xsb_existence_error(CTXTc "thread",reg[2],
00477                                   "xsb_thread_detach",1,1); 
00478             }
00479           }
00480           th_vec[id].detached = 1;
00481           break ;
00482 
00483        case XSB_THREAD_SELF:
00484          rc = id = xsb_thread_self() ;
00485          ctop_int( CTXTc 2, id ) ;
00486          break ;
00487 
00488         case XSB_MUTEX_INIT:            {
00489           Integer arg = ptoc_int(CTXTc 2) ;
00490           pthread_mutexattr_t attr ;
00491           id = (Integer) mem_alloc( sizeof(pthread_mutex_t),THREAD_SPACE ) ;
00492           pthread_mutexattr_init( &attr ) ;
00493           switch(arg)
00494             {
00495             case XSB_FAST_MUTEX:
00496               pthread_mutexattr_settype( &attr, 
00497                                          PTHREAD_MUTEX_FAST_NP ) ;
00498               break ;
00499             case XSB_RECURSIVE_MUTEX:
00500               pthread_mutexattr_settype( &attr, 
00501                                          PTHREAD_MUTEX_RECURSIVE_NP ) ;
00502               break ;
00503             case XSB_ERRORCHECK_MUTEX:
00504               pthread_mutexattr_settype( &attr, 
00505                                          PTHREAD_MUTEX_ERRORCHECK_NP ) ;
00506               break ;
00507             default:
00508               pthread_mutexattr_settype( &attr, 
00509                                          PTHREAD_MUTEX_FAST_NP ) ;
00510               break ;
00511             }
00512           rc = pthread_mutex_init( (pthread_mutex_t *)id, &attr ) ;
00513           if (rc == ENOMEM) {
00514             xsb_resource_error(th,"memory","xsb_mutex_init",2);
00515           }
00516           break ;
00517         }
00518                 case XSB_MUTEX_LOCK:
00519                   id = ptoc_int(CTXTc 2) ;
00520 #ifdef DEBUG_MUTEXES
00521                   fprintf( stddbg, "LOCK(%x)\n", id ) ;
00522 #endif
00523                   rc = pthread_mutex_lock( (pthread_mutex_t *)id ) ;
00524                   if (rc == EINVAL) {
00525                     xsb_permission_error(CTXTc "lock mutex","invalid mutex",
00526                                    reg[2],"xsb_mutex_lock",2); 
00527                   } else if (rc == EDEADLK) { 
00528                     xsb_permission_error(CTXTc "lock mutex","deadlocking mutex",
00529                                    reg[2],"xsb_mutex_lock",2); 
00530                   } 
00531                   break ;
00532 
00533                 case XSB_MUTEX_TRYLOCK:
00534                   id = ptoc_int(CTXTc 2) ;
00535                   rc = pthread_mutex_trylock( (pthread_mutex_t *)id ) ;
00536                   if (rc == EINVAL) {
00537                     xsb_permission_error(CTXTc "lock mutex","invalid mutex",
00538                                    reg[2],"xsb_mutex_lock",2); 
00539                   } else success = ( rc != EBUSY ) ;
00540                         break ;
00541 
00542                 case XSB_MUTEX_UNLOCK:
00543                   id = ptoc_int(CTXTc 2) ;
00544 #ifdef DEBUG_MUTEXES
00545                   fprintf( stddbg, "UNLOCK(%x)\n", id ) ;
00546 #endif
00547                   rc = pthread_mutex_unlock( (pthread_mutex_t *)id ) ;
00548                   if (rc == EINVAL) {
00549                     xsb_permission_error(CTXTc "unlock mutex","invalid mutex",
00550                                          reg[2],"xsb_mutex_unlock",2); 
00551                   } else if (rc == EPERM) { 
00552                     xsb_permission_error(CTXTc "unlock mutex",
00553                                          "mutex not held by thread",
00554                                          reg[2],"xsb_mutex_unlock",2); 
00555                   } 
00556                   break ;
00557 
00558                 case XSB_MUTEX_DESTROY:
00559                   id = ptoc_int(CTXTc 2) ;
00560                   rc = pthread_mutex_destroy( (pthread_mutex_t *)id ) ;
00561                   if (rc == EINVAL) {
00562                     xsb_permission_error(CTXTc "destroy mutex","invalid mutex",
00563                                          reg[2],"xsb_mutex_destroy",1); 
00564                   } else {
00565                     if (rc == EBUSY) { 
00566                       xsb_permission_error(CTXTc "destroy mutex",
00567                                            "busy mutex",
00568                                            reg[2],"xsb_mutex_destroy",1); 
00569                     } else 
00570                       mem_dealloc( (pthread_mutex_t *)id, sizeof(pthread_mutex_t),
00571                                    THREAD_SPACE ) ;
00572                   }
00573                   break ;
00574 
00575                 case XSB_SYS_MUTEX_LOCK:
00576                   id = ptoc_int(CTXTc 2) ;
00577 #ifdef DEBUG_MUTEXES
00578                   fprintf( stddbg, "S LOCK(%ld)\n", (long)id ) ;
00579 #endif
00580                   rc = pthread_mutex_lock( MUTARRAY_MUTEX(id) ) ;
00581 #ifdef DEBUG_MUTEXES
00582                   fprintf( stddbg, "RC=%ld\n", (long)rc ) ;
00583 #endif
00584                   break ;
00585                 case XSB_SYS_MUTEX_UNLOCK:
00586                         id = ptoc_int(CTXTc 2) ;
00587 #ifdef DEBUG_MUTEXES
00588                         fprintf( stddbg, "S UNLOCK(%ld)\n", (long)id ) ;
00589 #endif
00590                         rc = pthread_mutex_unlock( MUTARRAY_MUTEX(id) ) ;
00591 #ifdef DEBUG_MUTEXES
00592                         fprintf( stddbg, "RC=%ld\n", (long)rc ) ;
00593 #endif
00594                         break ;
00595 
00596         case XSB_ENSURE_ONE_THREAD:
00597           ENSURE_ONE_THREAD() ;
00598           rc = 0 ;
00599           break ;
00600 
00601           /*TLS: I should make the configuration check for existence
00602             of sched_yield somehow. */
00603         case XSB_THREAD_YIELD:
00604 #if !defined(SOLARIS)
00605           rc = sched_yield();
00606           if (rc == ENOSYS) /* Need support for POSIX 1b for this */
00607 #endif
00608             xsb_abort("Real-time extensions not supported on this platform");
00609           break;
00610 
00611         case XSB_SHOW_MUTEXES: 
00612           printf("mutex owners\n");
00613           for (i = 0; i < MAX_SYS_MUTEXES; i++) {
00614             if (sys_mut[i].owner > 0) 
00615               printf("Mutex %s (%d): %d\n",mutex_names[i],i,sys_mut[i].owner);
00616           }
00617           rc = 0;
00618           break;
00619 
00620         case XSB_SET_INIT_GLSTACK_SIZE:
00621           i = ptoc_int(CTXTc 2) ;
00622           set_init_glstack_size(i);
00623           rc = 0;
00624           break;
00625         case XSB_SET_INIT_TCPSTACK_SIZE:
00626           i = ptoc_int(CTXTc 2) ;
00627           set_init_tcpstack_size(i);
00628           rc = 0;
00629           break;
00630         case XSB_SET_INIT_PDL_SIZE:
00631           i = ptoc_int(CTXTc 2) ;
00632           set_init_pdl_size(i);
00633           rc = 0;
00634           break;
00635         case XSB_SET_INIT_COMPLSTACK_SIZE:
00636           i = ptoc_int(CTXTc 2) ;
00637           set_init_complstack_size(i);
00638           rc = 0;
00639           break;
00640 
00641           /* TLS: may generalize -- right now, just detached/joinable */
00642         case XSB_THREAD_PROPERTY: 
00643           ctop_int(CTXTc 3, th_vec[ ptoc_int(CTXTc 2) ].detached);
00644           break;
00645 
00646           /* for now, one interrupt, but possibly we should allow
00647              users to define others  */
00648         case XSB_THREAD_INTERRUPT: {
00649           th_context *  ctxt_ptr ;
00650 
00651           i = ptoc_int(CTXTc 2);
00652           if (th_vec[i].valid) {
00653             ctxt_ptr = th_vec[i].ctxt;
00654             ctxt_ptr->_asynint_val |= THREADINT_MARK;
00655           } else {
00656             bld_int(reg+2,i);
00657             xsb_permission_error(CTXTc "thread_interrupt","invalid_thread",
00658                                    reg[2],"xsb_thread_interrupt",1); 
00659           }
00660           break;
00661         }
00662 
00663         case ABOLISH_PRIVATE_TABLES: {
00664           abolish_private_tables(CTXT);
00665           break;
00666         }
00667 
00668         case ABOLISH_SHARED_TABLES: {
00669           abolish_shared_tables(CTXT);
00670           break;
00671         }
00672 
00673         default:
00674           rc = 0 ; /* Keep compiler happy */
00675           xsb_abort( "[THREAD] Invalid thread operation requested %d",request_num);
00676           break ;
00677         }
00678         //      ctop_int( CTXTc 5, rc ) ;
00679         return success ;
00680 #else
00681         switch( request_num )
00682         {
00683                 
00684                 case XSB_THREAD_SELF:
00685                         ctop_int( CTXTc 2, xsb_thread_self() ) ;
00686                         break;
00687                 case XSB_SYS_MUTEX_LOCK:
00688                 case XSB_SYS_MUTEX_UNLOCK:
00689                         break ;
00690                 case XSB_ENSURE_ONE_THREAD:
00691                         break ;
00692                 case XSB_THREAD_YIELD:
00693                         break ;
00694                 default:
00695                         xsb_abort( "[THREAD] Thread primitives not compiled" ) ;
00696                         break ;
00697         }
00698         
00699         ctop_int( CTXTc 5, 0 ) ;
00700         return TRUE ;
00701 #endif /* MULTI_THREAD */
00702 }
00703 
00704 xsbBool mt_random_request( CTXTdecl )
00705 {
00706 
00707   Integer request_num = ptoc_int(CTXTc 1) ;
00708 
00709   switch( request_num )
00710     {
00711     case INIT_MT_RANDOM:
00712      SRANDOM_CALL(time(0)); 
00713       break;
00714 
00715     case MT_RANDOM:
00716             ctop_int(CTXTc 2,RANDOM_CALL());
00717       break;
00718 
00719     case MT_RANDOM_INTERVAL:
00720       {
00721         UInteger rval;
00722         UInteger scale = ptoc_int(CTXTc 2);
00723         UInteger interval = ((unsigned long) pow(2,32) - 1) / scale;
00724         //      printf("max %lx\n",((unsigned long) pow(2,32)-1));
00725         //      printf("int %x scale %x s1 %d ex %x\n", interval,scale,scale,16);
00726         rval = RANDOM_CALL(); 
00727         //      printf("rval %x \n",rval);
00728         ctop_int(CTXTc 3,(Integer)floor(rval / interval));
00729         break;
00730       }
00731 
00732     default: 
00733       xsb_abort( "[THREAD] Improper case for mt_rand" ) ;
00734     }
00735   return TRUE ;
00736 }
00737 

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