00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #undef __STRICT_ANSI__
00028
00029 #include "xsb_debug.h"
00030 #include "xsb_config.h"
00031
00032 #ifdef WIN_NT
00033 #include <windows.h>
00034 #include <winuser.h>
00035 #else
00036 #include <sys/types.h>
00037 #include <stdlib.h>
00038 #include <signal.h>
00039 #include <unistd.h>
00040 #include <errno.h>
00041 #endif
00042
00043 #include <stdio.h>
00044
00045 #include "xsb_time.h"
00046 #include "cell_xsb.h"
00047 #include "error_xsb.h"
00048 #include "setjmp_xsb.h"
00049 #include "timer_xsb.h"
00050 #include "basicdefs.h"
00051 #include "thread_xsb.h"
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 #ifdef MULTI_THREAD
00139
00140 void init_machine(CTXTdeclc int, int, int, int);
00141
00142 #else
00143
00144 #ifdef WIN_NT
00145 static int exitFlag = STILL_WAITING;
00146 static long timedThread;
00147 HANDLE sockEvent = NULL;
00148 #else
00149 sigjmp_buf xsb_timer_env;
00150 #endif
00151
00152 #endif
00153
00154 #ifdef MULTI_THREAD
00155 int op_timed_out(CTXTdeclc xsbTimeout *timeout)
00156 {
00157 struct timespec wakeup_time;
00158 int rc;
00159
00160 wakeup_time.tv_sec = time(NULL) + (int)pflags[SYS_TIMER];
00161 pthread_mutex_lock(&timeout->timeout_info.mutex);
00162 rc = pthread_cond_timedwait(&timeout->timeout_info.condition,
00163 &timeout->timeout_info.mutex, &wakeup_time);
00164 pthread_mutex_unlock(&timeout->timeout_info.mutex);
00165 if (rc != 0) {
00166 switch(rc) {
00167 case EINVAL:
00168 xsb_bug("pthread_cond_timedwait returned EINVAL");
00169 break;
00170 case ETIMEDOUT:
00171 break;
00172 case ENOMEM:
00173 xsb_error("Not enough memory to wait\n");
00174 break;
00175 default:
00176 xsb_bug("pthread_cond_timedwait returned an unexpected value (%d)\n", rc);
00177 }
00178 }
00179 TURNOFFALARM;
00180 switch (timeout->timeout_info.exitFlag) {
00181 case STILL_WAITING:
00182 PTHREAD_CANCEL(timeout->timeout_info.timedThread);
00183 return TRUE;
00184 case TIMED_OUT:
00185 return TRUE;
00186 case NORMAL_TERMINATION:
00187 return FALSE;
00188 default:
00189 xsb_bug("timed call's exit flag is an unexpected value (%d)", timeout->timeout_info.exitFlag);
00190 return FALSE;
00191 }
00192 }
00193
00194 #else
00195
00196 #ifdef WIN_NT
00197 VOID CALLBACK xsb_timer_handler(HWND wind, UINT msg, UINT eventid, DWORD time)
00198 {
00199 if (exitFlag == STILL_WAITING)
00200 exitFlag = TIMED_OUT;
00201 TerminateThread((HANDLE)timedThread, 1);
00202 }
00203
00204
00205 int message_pump()
00206 {
00207 MSG msg;
00208 if ((xsb_timer_id = SetTimer(NULL,
00209 0,
00210
00211 (UINT)((int)pflags[SYS_TIMER] * 1000),
00212 (TIMERPROC)xsb_timer_handler))
00213 == 0) {
00214 xsb_error("SOCKET_REQUEST: Can't create timer: %d\n", GetLastError());
00215 return TIMER_SETUP_ERR;
00216 }
00217
00218 exitFlag=STILL_WAITING;
00219 while ((exitFlag==STILL_WAITING) && GetMessage(&msg,NULL,0,0)) {
00220 DispatchMessage(&msg);
00221 if (msg.wParam == NORMAL_TERMINATION)
00222 break;
00223 }
00224
00225 if (xsb_timer_id != 0)
00226 TURNOFFALARM;
00227
00228 if (exitFlag == TIMED_OUT)
00229 return TRUE;
00230 else
00231 return FALSE;
00232 }
00233
00234 #else
00235
00236
00237 void xsb_timer_handler(int signo)
00238 {
00239 siglongjmp(xsb_timer_env,1);
00240 }
00241
00242 #endif
00243
00244 #endif
00245
00246
00247
00248
00249 int make_timed_call(CTXTdeclc xsbTimeout *pptr, void (*fptr)(xsbTimeout *))
00250 {
00251 #if defined(WIN_NT) || defined(MULTI_THREAD)
00252 int return_msg;
00253 #endif
00254
00255 #ifdef MULTI_THREAD
00256
00257 #ifdef WIN_NT
00258 pptr->timeout_info.timedThread = mem_alloc(sizeof(pthread_t),LEAK_SPACE);
00259 #define TIMED_THREAD_CREATE_ARG pptr->timeout_info.timedThread
00260 #else
00261 #define TIMED_THREAD_CREATE_ARG &pptr->timeout_info.timedThread
00262 #endif
00263 pptr->timeout_info.th=th;
00264
00265
00266 if (pthread_create(TIMED_THREAD_CREATE_ARG, NULL, fptr, pptr)) {
00267 xsb_error("SOCKET_REQUEST: Can't create concurrent timer thread\n");
00268 return TIMER_SETUP_ERR;
00269 }
00270 PTHREAD_DETACH(pptr->timeout_info.timedThread);
00271 return_msg = OP_TIMED_OUT(pptr);
00272 #ifdef WIN_NT
00273 mem_dealloc(pptr->timeout_info.timedThread,sizeof(pthread_t),LEAK_SPACE);
00274 #endif
00275 if (return_msg == TIMER_SETUP_ERR) {
00276 return TIMER_SETUP_ERR;
00277 } else if (!return_msg) {
00278 TURNOFFALARM;
00279 return FALSE;
00280 } else {
00281 TURNOFFALARM;
00282 return TRUE;
00283 }
00284
00285 #else
00286
00287 #ifdef WIN_NT
00288
00289
00290 pptr->timeout_info.parent_thread = (long)GetCurrentThreadId();
00291 if((timedThread = _beginthread(fptr,0,(void*)(pptr)))==-1) {
00292 xsb_error("SOCKET_REQUEST: Can't create concurrent timer thread\n");
00293 return TIMER_SETUP_ERR;
00294 }
00295 return_msg = OP_TIMED_OUT(pptr);
00296
00297 if (return_msg == TIMER_SETUP_ERR) {
00298 return TIMER_SETUP_ERR;
00299 } else if (!return_msg) {
00300 TURNOFFALARM;
00301 return FALSE;
00302 } else {
00303 TURNOFFALARM;
00304 return TRUE;
00305 }
00306 #else
00307 SETALARM;
00308
00309
00310 if ( !OP_TIMED_OUT ) {
00311 SET_TIMER;
00312 (*fptr)(CTXTc pptr);
00313 TURNOFFALARM;
00314 return FALSE;
00315 } else {
00316 TURNOFFALARM;
00317 return TRUE;
00318 }
00319
00320 #endif
00321
00322 #endif
00323
00324 }