@@ -64,10 +64,8 @@ typedef sig_t sighandler_t;
64
64
65
65
#endif
66
66
67
- #if !defined(_WIN32 )
68
- /* enable the os.Worker API. IT relies on POSIX threads */
67
+ /* enable the os.Worker API. It relies on POSIX threads */
69
68
#define USE_WORKER
70
- #endif
71
69
72
70
#ifdef USE_WORKER
73
71
#include <pthread.h>
@@ -114,14 +112,22 @@ typedef struct {
114
112
size_t sab_tab_len ;
115
113
} JSWorkerMessage ;
116
114
115
+ typedef struct JSWaker {
116
+ #ifdef _WIN32
117
+ HANDLE handle ;
118
+ #else
119
+ int read_fd ;
120
+ int write_fd ;
121
+ #endif
122
+ } JSWaker ;
123
+
117
124
typedef struct {
118
125
int ref_count ;
119
126
#ifdef USE_WORKER
120
127
pthread_mutex_t mutex ;
121
128
#endif
122
129
struct list_head msg_queue ; /* list of JSWorkerMessage.link */
123
- int read_fd ;
124
- int write_fd ;
130
+ JSWaker waker ;
125
131
} JSWorkerMessagePipe ;
126
132
127
133
typedef struct {
@@ -2138,82 +2144,81 @@ static void call_handler(JSContext *ctx, JSValueConst func)
2138
2144
JS_FreeValue (ctx , ret );
2139
2145
}
2140
2146
2141
- #if defined( _WIN32 )
2147
+ #ifdef USE_WORKER
2142
2148
2143
- static int js_os_poll (JSContext * ctx )
2149
+ #ifdef _WIN32
2150
+
2151
+ static int js_waker_init (JSWaker * w )
2144
2152
{
2145
- JSRuntime * rt = JS_GetRuntime (ctx );
2146
- JSThreadState * ts = JS_GetRuntimeOpaque (rt );
2147
- int min_delay , console_fd ;
2148
- int64_t cur_time , delay ;
2149
- JSOSRWHandler * rh ;
2150
- struct list_head * el ;
2153
+ w -> handle = CreateEvent (NULL , TRUE, FALSE, NULL );
2154
+ return w -> handle ? 0 : -1 ;
2155
+ }
2151
2156
2152
- /* XXX: handle signals if useful */
2157
+ static void js_waker_signal (JSWaker * w )
2158
+ {
2159
+ SetEvent (w -> handle );
2160
+ }
2153
2161
2154
- if (list_empty (& ts -> os_rw_handlers ) && list_empty (& ts -> os_timers ))
2155
- return -1 ; /* no more events */
2162
+ static void js_waker_clear (JSWaker * w )
2163
+ {
2164
+ ResetEvent (w -> handle );
2165
+ }
2156
2166
2157
- /* XXX: only timers and basic console input are supported */
2158
- if (!list_empty (& ts -> os_timers )) {
2159
- cur_time = get_time_ms ();
2160
- min_delay = 10000 ;
2161
- list_for_each (el , & ts -> os_timers ) {
2162
- JSOSTimer * th = list_entry (el , JSOSTimer , link );
2163
- delay = th -> timeout - cur_time ;
2164
- if (delay <= 0 ) {
2165
- JSValue func ;
2166
- /* the timer expired */
2167
- func = th -> func ;
2168
- th -> func = JS_UNDEFINED ;
2169
- free_timer (rt , th );
2170
- call_handler (ctx , func );
2171
- JS_FreeValue (ctx , func );
2172
- return 0 ;
2173
- } else if (delay < min_delay ) {
2174
- min_delay = delay ;
2175
- }
2176
- }
2177
- } else {
2178
- min_delay = -1 ;
2179
- }
2167
+ static void js_waker_close (JSWaker * w )
2168
+ {
2169
+ CloseHandle (w -> handle );
2170
+ w -> handle = INVALID_HANDLE_VALUE ;
2171
+ }
2180
2172
2181
- console_fd = -1 ;
2182
- list_for_each (el , & ts -> os_rw_handlers ) {
2183
- rh = list_entry (el , JSOSRWHandler , link );
2184
- if (rh -> fd == 0 && !JS_IsNull (rh -> rw_func [0 ])) {
2185
- console_fd = rh -> fd ;
2173
+ #else // !_WIN32
2174
+
2175
+ static int js_waker_init (JSWaker * w )
2176
+ {
2177
+ int fds [2 ];
2178
+
2179
+ if (pipe (fds ) < 0 )
2180
+ return -1 ;
2181
+ w -> read_fd = fds [0 ];
2182
+ w -> write_fd = fds [1 ];
2183
+ return 0 ;
2184
+ }
2185
+
2186
+ static void js_waker_signal (JSWaker * w )
2187
+ {
2188
+ int ret ;
2189
+
2190
+ for (;;) {
2191
+ ret = write (w -> write_fd , "" , 1 );
2192
+ if (ret == 1 )
2193
+ break ;
2194
+ if (ret < 0 && (errno != EAGAIN || errno != EINTR ))
2186
2195
break ;
2187
- }
2188
2196
}
2197
+ }
2189
2198
2190
- if (console_fd >= 0 ) {
2191
- DWORD ti , ret ;
2192
- HANDLE handle ;
2193
- if (min_delay == -1 )
2194
- ti = INFINITE ;
2195
- else
2196
- ti = min_delay ;
2197
- handle = (HANDLE )_get_osfhandle (console_fd );
2198
- ret = WaitForSingleObject (handle , ti );
2199
- if (ret == WAIT_OBJECT_0 ) {
2200
- list_for_each (el , & ts -> os_rw_handlers ) {
2201
- rh = list_entry (el , JSOSRWHandler , link );
2202
- if (rh -> fd == console_fd && !JS_IsNull (rh -> rw_func [0 ])) {
2203
- call_handler (ctx , rh -> rw_func [0 ]);
2204
- /* must stop because the list may have been modified */
2205
- break ;
2206
- }
2207
- }
2208
- }
2209
- } else {
2210
- Sleep (min_delay );
2199
+ static void js_waker_clear (JSWaker * w )
2200
+ {
2201
+ uint8_t buf [16 ];
2202
+ int ret ;
2203
+
2204
+ for (;;) {
2205
+ ret = read (w -> read_fd , buf , sizeof (buf ));
2206
+ if (ret >= 0 )
2207
+ break ;
2208
+ if (errno != EAGAIN && errno != EINTR )
2209
+ break ;
2211
2210
}
2212
- return 0 ;
2213
2211
}
2214
- #else
2215
2212
2216
- #ifdef USE_WORKER
2213
+ static void js_waker_close (JSWaker * w )
2214
+ {
2215
+ close (w -> read_fd );
2216
+ close (w -> write_fd );
2217
+ w -> read_fd = -1 ;
2218
+ w -> write_fd = -1 ;
2219
+ }
2220
+
2221
+ #endif // _WIN32
2217
2222
2218
2223
static void js_free_message (JSWorkerMessage * msg );
2219
2224
@@ -2235,17 +2240,8 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2235
2240
/* remove the message from the queue */
2236
2241
list_del (& msg -> link );
2237
2242
2238
- if (list_empty (& ps -> msg_queue )) {
2239
- uint8_t buf [16 ];
2240
- int ret ;
2241
- for (;;) {
2242
- ret = read (ps -> read_fd , buf , sizeof (buf ));
2243
- if (ret >= 0 )
2244
- break ;
2245
- if (errno != EAGAIN && errno != EINTR )
2246
- break ;
2247
- }
2248
- }
2243
+ if (list_empty (& ps -> msg_queue ))
2244
+ js_waker_clear (& ps -> waker );
2249
2245
2250
2246
pthread_mutex_unlock (& ps -> mutex );
2251
2247
@@ -2288,7 +2284,104 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2288
2284
{
2289
2285
return 0 ;
2290
2286
}
2291
- #endif
2287
+ #endif /* !USE_WORKER */
2288
+
2289
+ #if defined(_WIN32 )
2290
+
2291
+ static int js_os_poll (JSContext * ctx )
2292
+ {
2293
+ JSRuntime * rt = JS_GetRuntime (ctx );
2294
+ JSThreadState * ts = JS_GetRuntimeOpaque (rt );
2295
+ int min_delay , count ;
2296
+ int64_t cur_time , delay ;
2297
+ JSOSRWHandler * rh ;
2298
+ struct list_head * el ;
2299
+ HANDLE handles [MAXIMUM_WAIT_OBJECTS ]; // 64
2300
+
2301
+ /* XXX: handle signals if useful */
2302
+
2303
+ if (list_empty (& ts -> os_rw_handlers ) && list_empty (& ts -> os_timers ) &&
2304
+ list_empty (& ts -> port_list )) {
2305
+ return -1 ; /* no more events */
2306
+ }
2307
+
2308
+ if (!list_empty (& ts -> os_timers )) {
2309
+ cur_time = get_time_ms ();
2310
+ min_delay = 10000 ;
2311
+ list_for_each (el , & ts -> os_timers ) {
2312
+ JSOSTimer * th = list_entry (el , JSOSTimer , link );
2313
+ delay = th -> timeout - cur_time ;
2314
+ if (delay <= 0 ) {
2315
+ JSValue func ;
2316
+ /* the timer expired */
2317
+ func = th -> func ;
2318
+ th -> func = JS_UNDEFINED ;
2319
+ free_timer (rt , th );
2320
+ call_handler (ctx , func );
2321
+ JS_FreeValue (ctx , func );
2322
+ return 0 ;
2323
+ } else if (delay < min_delay ) {
2324
+ min_delay = delay ;
2325
+ }
2326
+ }
2327
+ } else {
2328
+ min_delay = -1 ;
2329
+ }
2330
+
2331
+ count = 0 ;
2332
+ list_for_each (el , & ts -> os_rw_handlers ) {
2333
+ rh = list_entry (el , JSOSRWHandler , link );
2334
+ if (rh -> fd == 0 && !JS_IsNull (rh -> rw_func [0 ])) {
2335
+ handles [count ++ ] = (HANDLE )_get_osfhandle (rh -> fd ); // stdin
2336
+ if (count == (int )countof (handles ))
2337
+ break ;
2338
+ }
2339
+ }
2340
+
2341
+ list_for_each (el , & ts -> port_list ) {
2342
+ JSWorkerMessageHandler * port = list_entry (el , JSWorkerMessageHandler , link );
2343
+ if (JS_IsNull (port -> on_message_func ))
2344
+ continue ;
2345
+ handles [count ++ ] = port -> recv_pipe -> waker .handle ;
2346
+ if (count == (int )countof (handles ))
2347
+ break ;
2348
+ }
2349
+
2350
+ if (count > 0 ) {
2351
+ DWORD ret , timeout = INFINITE ;
2352
+ if (min_delay != -1 )
2353
+ timeout = min_delay ;
2354
+ ret = WaitForMultipleObjects (count , handles , FALSE, timeout );
2355
+
2356
+ if (ret < count ) {
2357
+ list_for_each (el , & ts -> os_rw_handlers ) {
2358
+ rh = list_entry (el , JSOSRWHandler , link );
2359
+ if (rh -> fd == 0 && !JS_IsNull (rh -> rw_func [0 ])) {
2360
+ call_handler (ctx , rh -> rw_func [0 ]);
2361
+ /* must stop because the list may have been modified */
2362
+ goto done ;
2363
+ }
2364
+ }
2365
+
2366
+ list_for_each (el , & ts -> port_list ) {
2367
+ JSWorkerMessageHandler * port = list_entry (el , JSWorkerMessageHandler , link );
2368
+ if (!JS_IsNull (port -> on_message_func )) {
2369
+ JSWorkerMessagePipe * ps = port -> recv_pipe ;
2370
+ if (ps -> waker .handle == handles [ret ]) {
2371
+ if (handle_posted_message (rt , ctx , port ))
2372
+ goto done ;
2373
+ }
2374
+ }
2375
+ }
2376
+ }
2377
+ } else {
2378
+ Sleep (min_delay );
2379
+ }
2380
+ done :
2381
+ return 0 ;
2382
+ }
2383
+
2384
+ #else
2292
2385
2293
2386
static int js_os_poll (JSContext * ctx )
2294
2387
{
@@ -2364,8 +2457,8 @@ static int js_os_poll(JSContext *ctx)
2364
2457
JSWorkerMessageHandler * port = list_entry (el , JSWorkerMessageHandler , link );
2365
2458
if (!JS_IsNull (port -> on_message_func )) {
2366
2459
JSWorkerMessagePipe * ps = port -> recv_pipe ;
2367
- fd_max = max_int (fd_max , ps -> read_fd );
2368
- FD_SET (ps -> read_fd , & rfds );
2460
+ fd_max = max_int (fd_max , ps -> waker . read_fd );
2461
+ FD_SET (ps -> waker . read_fd , & rfds );
2369
2462
}
2370
2463
}
2371
2464
@@ -2391,14 +2484,14 @@ static int js_os_poll(JSContext *ctx)
2391
2484
JSWorkerMessageHandler * port = list_entry (el , JSWorkerMessageHandler , link );
2392
2485
if (!JS_IsNull (port -> on_message_func )) {
2393
2486
JSWorkerMessagePipe * ps = port -> recv_pipe ;
2394
- if (FD_ISSET (ps -> read_fd , & rfds )) {
2487
+ if (FD_ISSET (ps -> waker . read_fd , & rfds )) {
2395
2488
if (handle_posted_message (rt , ctx , port ))
2396
2489
goto done ;
2397
2490
}
2398
2491
}
2399
2492
}
2400
2493
}
2401
- done :
2494
+ done :
2402
2495
return 0 ;
2403
2496
}
2404
2497
#endif /* !_WIN32 */
@@ -3269,22 +3362,17 @@ static void js_sab_dup(void *opaque, void *ptr)
3269
3362
static JSWorkerMessagePipe * js_new_message_pipe (void )
3270
3363
{
3271
3364
JSWorkerMessagePipe * ps ;
3272
- int pipe_fds [2 ];
3273
-
3274
- if (pipe (pipe_fds ) < 0 )
3275
- return NULL ;
3276
3365
3277
3366
ps = malloc (sizeof (* ps ));
3278
- if (!ps ) {
3279
- close (pipe_fds [0 ]);
3280
- close (pipe_fds [1 ]);
3367
+ if (!ps )
3368
+ return NULL ;
3369
+ if (js_waker_init (& ps -> waker )) {
3370
+ free (ps );
3281
3371
return NULL ;
3282
3372
}
3283
3373
ps -> ref_count = 1 ;
3284
3374
init_list_head (& ps -> msg_queue );
3285
3375
pthread_mutex_init (& ps -> mutex , NULL );
3286
- ps -> read_fd = pipe_fds [0 ];
3287
- ps -> write_fd = pipe_fds [1 ];
3288
3376
return ps ;
3289
3377
}
3290
3378
@@ -3323,8 +3411,7 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps)
3323
3411
js_free_message (msg );
3324
3412
}
3325
3413
pthread_mutex_destroy (& ps -> mutex );
3326
- close (ps -> read_fd );
3327
- close (ps -> write_fd );
3414
+ js_waker_close (& ps -> waker );
3328
3415
free (ps );
3329
3416
}
3330
3417
}
@@ -3572,17 +3659,8 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val,
3572
3659
ps = worker -> send_pipe ;
3573
3660
pthread_mutex_lock (& ps -> mutex );
3574
3661
/* indicate that data is present */
3575
- if (list_empty (& ps -> msg_queue )) {
3576
- uint8_t ch = '\0' ;
3577
- int ret ;
3578
- for (;;) {
3579
- ret = write (ps -> write_fd , & ch , 1 );
3580
- if (ret == 1 )
3581
- break ;
3582
- if (ret < 0 && (errno != EAGAIN || errno != EINTR ))
3583
- break ;
3584
- }
3585
- }
3662
+ if (list_empty (& ps -> msg_queue ))
3663
+ js_waker_signal (& ps -> waker );
3586
3664
list_add_tail (& msg -> link , & ps -> msg_queue );
3587
3665
pthread_mutex_unlock (& ps -> mutex );
3588
3666
return JS_UNDEFINED ;
0 commit comments