1 /* In as much as this file simulates "foreign" code,
2 * we don't include "genesis/sbcl.h" and we use the native thread API
6 # include <handleapi.h>
8 # include <processthreadsapi.h>
9 # include <synchapi.h> // for WaitForSingleObject
17 struct thread_arg
{ void * funkyfun
; int index
; int n_calls
; };
19 char *salutations
[8] = {
20 "Hello", "Hi there!", "Hey", "Hi!", "Ahoy there", "What's up!", "Hola",
26 __stdcall
unsigned int perftest_thread(LPVOID void_arg
)
28 void* perftest_thread(void* void_arg
)
31 struct thread_arg
* arg
= void_arg
;
32 int (*lispfun
)() = arg
->funkyfun
;
33 int ncalls
= arg
->n_calls
;
35 for (i
=0; i
<ncalls
; ++i
) lispfun();
39 int minimal_perftest(void* ptr
, int n_calls
)
41 struct thread_arg arg
;
43 arg
.n_calls
= n_calls
;
46 thr
= (HANDLE
)_beginthreadex(NULL
, 0, perftest_thread
, &arg
, 0, NULL
);
47 WaitForSingleObject(thr
,0xffffffff);
51 pthread_create(&thr
, 0, perftest_thread
, &arg
);
58 __stdcall
unsigned int doThatThing(void* void_arg
)
60 void* doThatThing(void* void_arg
)
63 struct thread_arg
* arg
= void_arg
;
64 int thread_result
= 0xC0FEFE;
65 int (*lispfun
)(char*,double) = arg
->funkyfun
;
67 // fprintf(stderr, "enter doThatThing %p\n", void_arg); fflush(stderr);
68 for(i
=0; i
<arg
->n_calls
; ++i
) {
69 int index
= __sync_fetch_and_add(&sharedvar
,1);
70 char *salutation
= salutations
[index
% 8];
71 int answer
= lispfun(salutation
, arg
->index
+ i
);
72 if (answer
!= (arg
->index
+ i
) * strlen(salutation
)) thread_result
= 0;
74 return (void*)(uintptr_t)thread_result
;
77 int call_thing_from_threads(void* ptr
, int n_threads
, int n_calls
)
87 struct thread_arg arg
;
90 fprintf(stderr
, "pick a smaller number\n");
94 for(i
=0; i
<n_threads
; ++i
) {
95 threads
[i
].arg
.funkyfun
= ptr
;
96 threads
[i
].arg
.index
= i
+ 1;
97 threads
[i
].arg
.n_calls
= n_calls
;
99 threads
[i
].handle
= (HANDLE
)_beginthreadex(NULL
, 0, doThatThing
, &threads
[i
].arg
, 0, NULL
);
101 pthread_create(&threads
[i
].pthread_id
, 0, doThatThing
, &threads
[i
].arg
);
105 for(i
=0; i
<n_threads
; ++i
) {
108 // I don't know which header file defines INFINITE (for the timeout)
109 // so any large value should do.
110 result
= WaitForSingleObject(threads
[i
].handle
, 0xffffffff);
111 GetExitCodeThread(threads
[i
].handle
, &threads
[i
].result
);
112 CloseHandle(threads
[i
].handle
);
113 if (threads
[i
].result
!= 0xC0FEFE) all_ok
= 0;
115 pthread_join(threads
[i
].pthread_id
, &threads
[i
].result
);
117 fprintf(stderr
, "%d: pthread %lx returned %p\n",
118 i
, (long)threads
[i
].pthread_id
, threads
[i
].result
);
120 if ((uintptr_t)threads
[i
].result
!= 0xC0FEFE) all_ok
= 0;
126 /// The code following is for the no-lockup-on-exit test, unrelated to the above
127 /// FIXME: implement a watchdog timer for win32
130 #include <sys/time.h>
133 static pthread_mutex_t some_global_lock
= PTHREAD_MUTEX_INITIALIZER
;
135 void acquire_a_global_lock() {
136 pthread_mutex_lock(&some_global_lock
);
138 void release_a_global_lock() {
139 pthread_mutex_unlock(&some_global_lock
);
141 static void alarmclock_expired(int sig
)
143 char msg
[] = "timed out\n";
144 write(2, msg
, sizeof msg
-1);
148 /// Exit with failure if we can't exit within a set time.
149 void prepare_exit_test(int seconds
)
152 sa
.sa_handler
= alarmclock_expired
;
153 sigemptyset(&sa
.sa_mask
);
155 sigaction(SIGALRM
, &sa
, 0);
157 it
.it_value
.tv_sec
= seconds
;
158 it
.it_value
.tv_usec
= 0;
159 it
.it_interval
.tv_sec
= it
.it_interval
.tv_usec
= 0;
160 setitimer(ITIMER_REAL
, &it
, 0);