Transpose lines.
[sbcl.git] / tests / fcb-threads.c
blobf71e69fa57354edef9d5e5757441732d0fc6ca9d
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
3 * for the platform */
5 #ifdef _WIN32
6 # include <handleapi.h>
7 # include <process.h>
8 # include <processthreadsapi.h>
9 # include <synchapi.h> // for WaitForSingleObject
10 #else
11 # include <pthread.h>
12 #endif
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <string.h>
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",
21 "That's a winner"
23 int sharedvar;
25 #ifdef _WIN32
26 __stdcall unsigned int perftest_thread(LPVOID void_arg)
27 #else
28 void* perftest_thread(void* void_arg)
29 #endif
31 struct thread_arg* arg = void_arg;
32 int (*lispfun)() = arg->funkyfun;
33 int ncalls = arg->n_calls;
34 int i;
35 for (i=0; i<ncalls; ++i) lispfun();
36 return 0;
39 int minimal_perftest(void* ptr, int n_calls)
41 struct thread_arg arg;
42 arg.funkyfun = ptr;
43 arg.n_calls = n_calls;
44 #ifdef _WIN32
45 HANDLE thr;
46 thr = (HANDLE)_beginthreadex(NULL, 0, perftest_thread, &arg, 0, NULL);
47 WaitForSingleObject(thr,0xffffffff);
48 CloseHandle(thr);
49 #else
50 pthread_t thr;
51 pthread_create(&thr, 0, perftest_thread, &arg);
52 pthread_join(thr,0);
53 #endif
54 return 0;
57 #ifdef _WIN32
58 __stdcall unsigned int doThatThing(void* void_arg)
59 #else
60 void* doThatThing(void* void_arg)
61 #endif
63 struct thread_arg* arg = void_arg;
64 int thread_result = 0xC0FEFE;
65 int (*lispfun)(char*,double) = arg->funkyfun;
66 int i;
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)
79 struct {
80 #ifdef _WIN32
81 HANDLE handle;
82 DWORD result;
83 #else
84 pthread_t pthread_id;
85 void* result;
86 #endif
87 struct thread_arg arg;
88 } threads[50];
89 if (n_threads>50) {
90 fprintf(stderr, "pick a smaller number\n");
91 return -1;
93 int i;
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;
98 #ifdef _WIN32
99 threads[i].handle = (HANDLE)_beginthreadex(NULL, 0, doThatThing, &threads[i].arg, 0, NULL);
100 #else
101 pthread_create(&threads[i].pthread_id, 0, doThatThing, &threads[i].arg);
102 #endif
104 int all_ok = 1;
105 for(i=0; i<n_threads; ++i) {
106 #ifdef _WIN32
107 DWORD result;
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;
114 #else
115 pthread_join(threads[i].pthread_id, &threads[i].result);
116 #if 0
117 fprintf(stderr, "%d: pthread %lx returned %p\n",
118 i, (long)threads[i].pthread_id, threads[i].result);
119 #endif
120 if ((uintptr_t)threads[i].result != 0xC0FEFE) all_ok = 0;
121 #endif
123 return all_ok;
126 /// The code following is for the no-lockup-on-exit test, unrelated to the above
127 /// FIXME: implement a watchdog timer for win32
128 #ifndef _WIN32
129 #include <signal.h>
130 #include <sys/time.h>
131 #include <unistd.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);
145 _exit(1);
148 /// Exit with failure if we can't exit within a set time.
149 void prepare_exit_test(int seconds)
151 struct sigaction sa;
152 sa.sa_handler = alarmclock_expired;
153 sigemptyset(&sa.sa_mask);
154 sa.sa_flags = 0;
155 sigaction(SIGALRM, &sa, 0);
156 struct itimerval it;
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);
162 #endif