00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00055
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
00088
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
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
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
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
00165
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
00226
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
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
00260
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
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) {
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) {
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
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
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
00365
00366 void print_mutex_use() {
00367 xsb_abort("This engine is not configured for mutex profiling.");
00368 }
00369
00370 #endif
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
00409
00410
00411
00412
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 ;
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) {
00446 xsb_permission_error(CTXTc "thread_join","non-joinable thread",
00447 reg[2],"xsb_thread_join",1);
00448 } else {
00449 if (rc == ESRCH) {
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) {
00472 xsb_permission_error(CTXTc "thread_detach","non-joinable thread",
00473 reg[2],"xsb_thread_detach",1);
00474 } else {
00475 if (rc == ESRCH) {
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
00602
00603 case XSB_THREAD_YIELD:
00604 #if !defined(SOLARIS)
00605 rc = sched_yield();
00606 if (rc == ENOSYS)
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
00642 case XSB_THREAD_PROPERTY:
00643 ctop_int(CTXTc 3, th_vec[ ptoc_int(CTXTc 2) ].detached);
00644 break;
00645
00646
00647
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 ;
00675 xsb_abort( "[THREAD] Invalid thread operation requested %d",request_num);
00676 break ;
00677 }
00678
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
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
00725
00726 rval = RANDOM_CALL();
00727
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