37
37
#include <sys/sem.h>
38
38
#endif
39
39
40
+ #ifdef __GLIBC__
41
+ #include <gnu/libc-version.h> /* gnu_get_libc_version() */
42
+ #endif
43
+
40
44
#undef NANOSEC
41
45
#define NANOSEC ((uint64_t) 1e9)
42
46
@@ -419,109 +423,145 @@ int uv_sem_trywait(uv_sem_t* sem) {
419
423
return UV_EINVAL ; /* Satisfy the compiler. */
420
424
}
421
425
426
+ #else /* !(defined(__APPLE__) && defined(__MACH__)) */
427
+
428
+ #ifdef __GLIBC__
429
+
430
+ /* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
431
+ * by providing a custom implementation for glibc < 2.21 in terms of other
432
+ * concurrency primitives.
433
+ * Refs: https://github.com/nodejs/node/issues/19903 */
434
+
435
+ /* To preserve ABI compatibility, we treat the uv_sem_t as storage for
436
+ * a pointer to the actual struct we're using underneath. */
437
+
438
+ static uv_once_t glibc_version_check_once = UV_ONCE_INIT ;
439
+ static int platform_needs_custom_semaphore = 0 ;
440
+
441
+ static void glibc_version_check (void ) {
442
+ const char * version = gnu_get_libc_version ();
443
+ platform_needs_custom_semaphore =
444
+ version [0 ] == '2' && version [1 ] == '.' &&
445
+ atoi (version + 2 ) < 21 ;
446
+ }
447
+
422
448
#elif defined(__MVS__ )
423
449
424
- int uv_sem_init (uv_sem_t * sem , unsigned int value ) {
425
- uv_sem_t semid ;
450
+ #define platform_needs_custom_semaphore 1
451
+
452
+ #else /* !defined(__GLIBC__) && !defined(__MVS__) */
453
+
454
+ #define platform_needs_custom_semaphore 0
455
+
456
+ #endif
457
+
458
+ typedef struct uv_semaphore_s {
459
+ uv_mutex_t mutex ;
460
+ uv_cond_t cond ;
461
+ unsigned int value ;
462
+ } uv_semaphore_t ;
463
+
464
+ #if defined(__GLIBC__ ) || platform_needs_custom_semaphore
465
+ STATIC_ASSERT (sizeof (uv_sem_t ) >= sizeof (uv_semaphore_t * ));
466
+ #endif
467
+
468
+ static int uv__custom_sem_init (uv_sem_t * sem_ , unsigned int value ) {
426
469
int err ;
427
- union {
428
- int val ;
429
- struct semid_ds * buf ;
430
- unsigned short * array ;
431
- } arg ;
470
+ uv_semaphore_t * sem ;
432
471
472
+ sem = uv__malloc (sizeof (* sem ));
473
+ if (sem == NULL )
474
+ return UV_ENOMEM ;
433
475
434
- semid = semget (IPC_PRIVATE , 1 , S_IRUSR | S_IWUSR );
435
- if (semid == -1 )
436
- return UV__ERR (errno );
476
+ if ((err = uv_mutex_init (& sem -> mutex )) != 0 ) {
477
+ uv__free (sem );
478
+ return err ;
479
+ }
437
480
438
- arg .val = value ;
439
- if (-1 == semctl (semid , 0 , SETVAL , arg )) {
440
- err = errno ;
441
- if (-1 == semctl (* sem , 0 , IPC_RMID ))
442
- abort ();
443
- return UV__ERR (err );
481
+ if ((err = uv_cond_init (& sem -> cond )) != 0 ) {
482
+ uv_mutex_destroy (& sem -> mutex );
483
+ uv__free (sem );
484
+ return err ;
444
485
}
445
486
446
- * sem = semid ;
487
+ sem -> value = value ;
488
+ * (uv_semaphore_t * * )sem_ = sem ;
447
489
return 0 ;
448
490
}
449
491
450
- void uv_sem_destroy (uv_sem_t * sem ) {
451
- if (-1 == semctl (* sem , 0 , IPC_RMID ))
452
- abort ();
492
+
493
+ static void uv__custom_sem_destroy (uv_sem_t * sem_ ) {
494
+ uv_semaphore_t * sem ;
495
+
496
+ sem = * (uv_semaphore_t * * )sem_ ;
497
+ uv_cond_destroy (& sem -> cond );
498
+ uv_mutex_destroy (& sem -> mutex );
499
+ uv__free (sem );
453
500
}
454
501
455
- void uv_sem_post (uv_sem_t * sem ) {
456
- struct sembuf buf ;
457
502
458
- buf .sem_num = 0 ;
459
- buf .sem_op = 1 ;
460
- buf .sem_flg = 0 ;
503
+ static void uv__custom_sem_post (uv_sem_t * sem_ ) {
504
+ uv_semaphore_t * sem ;
461
505
462
- if (-1 == semop (* sem , & buf , 1 ))
463
- abort ();
506
+ sem = * (uv_semaphore_t * * )sem_ ;
507
+ uv_mutex_lock (& sem -> mutex );
508
+ sem -> value ++ ;
509
+ if (sem -> value == 1 )
510
+ uv_cond_signal (& sem -> cond );
511
+ uv_mutex_unlock (& sem -> mutex );
464
512
}
465
513
466
- void uv_sem_wait (uv_sem_t * sem ) {
467
- struct sembuf buf ;
468
- int op_status ;
469
-
470
- buf .sem_num = 0 ;
471
- buf .sem_op = -1 ;
472
- buf .sem_flg = 0 ;
473
514
474
- do
475
- op_status = semop (* sem , & buf , 1 );
476
- while (op_status == -1 && errno == EINTR );
515
+ static void uv__custom_sem_wait (uv_sem_t * sem_ ) {
516
+ uv_semaphore_t * sem ;
477
517
478
- if (op_status )
479
- abort ();
518
+ sem = * (uv_semaphore_t * * )sem_ ;
519
+ uv_mutex_lock (& sem -> mutex );
520
+ while (sem -> value == 0 )
521
+ uv_cond_wait (& sem -> cond , & sem -> mutex );
522
+ sem -> value -- ;
523
+ uv_mutex_unlock (& sem -> mutex );
480
524
}
481
525
482
- int uv_sem_trywait (uv_sem_t * sem ) {
483
- struct sembuf buf ;
484
- int op_status ;
485
526
486
- buf .sem_num = 0 ;
487
- buf .sem_op = -1 ;
488
- buf .sem_flg = IPC_NOWAIT ;
527
+ static int uv__custom_sem_trywait (uv_sem_t * sem_ ) {
528
+ uv_semaphore_t * sem ;
489
529
490
- do
491
- op_status = semop ( * sem , & buf , 1 );
492
- while ( op_status == -1 && errno == EINTR ) ;
530
+ sem = * ( uv_semaphore_t * * ) sem_ ;
531
+ if ( uv_mutex_trylock ( & sem -> mutex ) != 0 )
532
+ return UV_EAGAIN ;
493
533
494
- if (op_status ) {
495
- if (errno == EAGAIN )
496
- return UV_EAGAIN ;
497
- abort ();
534
+ if (sem -> value == 0 ) {
535
+ uv_mutex_unlock (& sem -> mutex );
536
+ return UV_EAGAIN ;
498
537
}
499
538
539
+ sem -> value -- ;
540
+ uv_mutex_unlock (& sem -> mutex );
541
+
500
542
return 0 ;
501
543
}
502
544
503
- #else /* !(defined(__APPLE__) && defined(__MACH__)) */
504
-
505
- int uv_sem_init (uv_sem_t * sem , unsigned int value ) {
545
+ static int uv__sem_init (uv_sem_t * sem , unsigned int value ) {
506
546
if (sem_init (sem , 0 , value ))
507
547
return UV__ERR (errno );
508
548
return 0 ;
509
549
}
510
550
511
551
512
- void uv_sem_destroy (uv_sem_t * sem ) {
552
+ static void uv__sem_destroy (uv_sem_t * sem ) {
513
553
if (sem_destroy (sem ))
514
554
abort ();
515
555
}
516
556
517
557
518
- void uv_sem_post (uv_sem_t * sem ) {
558
+ static void uv__sem_post (uv_sem_t * sem ) {
519
559
if (sem_post (sem ))
520
560
abort ();
521
561
}
522
562
523
563
524
- void uv_sem_wait (uv_sem_t * sem ) {
564
+ static void uv__sem_wait (uv_sem_t * sem ) {
525
565
int r ;
526
566
527
567
do
@@ -533,7 +573,7 @@ void uv_sem_wait(uv_sem_t* sem) {
533
573
}
534
574
535
575
536
- int uv_sem_trywait (uv_sem_t * sem ) {
576
+ static int uv__sem_trywait (uv_sem_t * sem ) {
537
577
int r ;
538
578
539
579
do
@@ -549,6 +589,49 @@ int uv_sem_trywait(uv_sem_t* sem) {
549
589
return 0 ;
550
590
}
551
591
592
+ int uv_sem_init (uv_sem_t * sem , unsigned int value ) {
593
+ #ifdef __GLIBC__
594
+ uv_once (& glibc_version_check_once , glibc_version_check );
595
+ #endif
596
+
597
+ if (platform_needs_custom_semaphore )
598
+ return uv__custom_sem_init (sem , value );
599
+ else
600
+ return uv__sem_init (sem , value );
601
+ }
602
+
603
+
604
+ void uv_sem_destroy (uv_sem_t * sem ) {
605
+ if (platform_needs_custom_semaphore )
606
+ uv__custom_sem_destroy (sem );
607
+ else
608
+ uv__sem_destroy (sem );
609
+ }
610
+
611
+
612
+ void uv_sem_post (uv_sem_t * sem ) {
613
+ if (platform_needs_custom_semaphore )
614
+ uv__custom_sem_post (sem );
615
+ else
616
+ uv__sem_post (sem );
617
+ }
618
+
619
+
620
+ void uv_sem_wait (uv_sem_t * sem ) {
621
+ if (platform_needs_custom_semaphore )
622
+ uv__custom_sem_wait (sem );
623
+ else
624
+ uv__sem_wait (sem );
625
+ }
626
+
627
+
628
+ int uv_sem_trywait (uv_sem_t * sem ) {
629
+ if (platform_needs_custom_semaphore )
630
+ return uv__custom_sem_trywait (sem );
631
+ else
632
+ return uv__sem_trywait (sem );
633
+ }
634
+
552
635
#endif /* defined(__APPLE__) && defined(__MACH__) */
553
636
554
637
0 commit comments