@@ -392,7 +392,7 @@ static void *tiny_sbrk(ptrdiff_t increment)
392
392
#define sbrk tiny_sbrk
393
393
# endif /* ECOS */
394
394
395
- #if ( defined(NETBSD ) || defined( OPENBSD ) ) && defined(__ELF__ )
395
+ #if defined(NETBSD ) && defined(__ELF__ )
396
396
ptr_t GC_data_start ;
397
397
398
398
void GC_init_netbsd_elf ()
@@ -405,6 +405,102 @@ static void *tiny_sbrk(ptrdiff_t increment)
405
405
}
406
406
#endif
407
407
408
+ #if defined(OPENBSD )
409
+ static struct sigaction old_segv_act ;
410
+ sigjmp_buf GC_jmp_buf_openbsd ;
411
+
412
+ # if defined(GC_OPENBSD_THREADS )
413
+ # include <sys/syscall.h>
414
+ sigset_t __syscall (quad_t , ...);
415
+ # endif
416
+
417
+ /*
418
+ * Dont use GC_find_limit() because siglongjmp out of the
419
+ * signal handler by-passes our userland pthreads lib, leaving
420
+ * SIGSEGV and SIGPROF masked. Instead use this custom one
421
+ * that works-around the issues.
422
+ */
423
+
424
+ /*ARGSUSED*/
425
+ void GC_fault_handler_openbsd (int sig )
426
+ {
427
+ siglongjmp (GC_jmp_buf_openbsd , 1 );
428
+ }
429
+
430
+ /* Return the first nonaddressible location > p or bound */
431
+ /* Requires allocation lock. */
432
+ ptr_t GC_find_limit_openbsd (ptr_t p , ptr_t bound )
433
+ {
434
+ static volatile ptr_t result ;
435
+ /* Safer if static, since otherwise it may not be */
436
+ /* preserved across the longjmp. Can safely be */
437
+ /* static since it's only called with the */
438
+ /* allocation lock held. */
439
+ struct sigaction act ;
440
+ size_t pgsz = (size_t )sysconf (_SC_PAGESIZE );
441
+
442
+ GC_ASSERT (I_HOLD_LOCK ());
443
+
444
+ act .sa_handler = GC_fault_handler_openbsd ;
445
+ sigemptyset (& act .sa_mask );
446
+ act .sa_flags = SA_NODEFER | SA_RESTART ;
447
+ sigaction (SIGSEGV , & act , & old_segv_act );
448
+
449
+ if (sigsetjmp (GC_jmp_buf_openbsd , 1 ) == 0 ) {
450
+ result = (ptr_t )(((word )(p )) & ~(pgsz - 1 ));
451
+ for (;;) {
452
+ result += pgsz ;
453
+ if (result >= bound ) {
454
+ result = bound ;
455
+ break ;
456
+ }
457
+ GC_noop1 ((word )(* result ));
458
+ }
459
+ }
460
+
461
+ # if defined(GC_OPENBSD_THREADS )
462
+ /* due to the siglongjump we need to manually unmask SIGPROF */
463
+ __syscall (SYS_sigprocmask , SIG_UNBLOCK , sigmask (SIGPROF ));
464
+ # endif
465
+
466
+ sigaction (SIGSEGV , & old_segv_act , 0 );
467
+
468
+ return (result );
469
+ }
470
+
471
+ /* Return first addressable location > p or bound */
472
+ /* Requires allocation lock. */
473
+ ptr_t GC_skip_hole_openbsd (ptr_t p , ptr_t bound )
474
+ {
475
+ static volatile ptr_t result ;
476
+ struct sigaction act ;
477
+ size_t pgsz = (size_t )sysconf (_SC_PAGESIZE );
478
+ static volatile int firstpass ;
479
+
480
+ GC_ASSERT (I_HOLD_LOCK ());
481
+
482
+ act .sa_handler = GC_fault_handler_openbsd ;
483
+ sigemptyset (& act .sa_mask );
484
+ act .sa_flags = SA_NODEFER | SA_RESTART ;
485
+ sigaction (SIGSEGV , & act , & old_segv_act );
486
+
487
+ firstpass = 1 ;
488
+ result = (ptr_t )(((word )(p )) & ~(pgsz - 1 ));
489
+ if (sigsetjmp (GC_jmp_buf_openbsd , 1 ) != 0 || firstpass ) {
490
+ firstpass = 0 ;
491
+ result += pgsz ;
492
+ if (result >= bound ) {
493
+ result = bound ;
494
+ } else
495
+ GC_noop1 ((word )(* result ));
496
+ }
497
+
498
+ sigaction (SIGSEGV , & old_segv_act , 0 );
499
+
500
+ return (result );
501
+ }
502
+ #endif
503
+
408
504
# ifdef OS2
409
505
410
506
# include <stddef.h>
@@ -1021,7 +1117,8 @@ void *GC_set_stackbottom = NULL;
1021
1117
#endif /* FREEBSD_STACKBOTTOM */
1022
1118
1023
1119
#if !defined(BEOS ) && !defined(AMIGA ) && !defined(MSWIN32 ) \
1024
- && !defined(MSWINCE ) && !defined(OS2 ) && !defined(NOSYS ) && !defined(ECOS )
1120
+ && !defined(MSWINCE ) && !defined(OS2 ) && !defined(NOSYS ) && !defined(ECOS ) \
1121
+ && !defined(GC_OPENBSD_THREADS )
1025
1122
1026
1123
ptr_t GC_get_stack_base ()
1027
1124
{
@@ -1081,6 +1178,25 @@ ptr_t GC_get_stack_base()
1081
1178
1082
1179
# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
1083
1180
1181
+ #if defined(GC_OPENBSD_THREADS )
1182
+
1183
+ /* Find the stack using pthread_stackseg_np() */
1184
+
1185
+ # include <sys/signal.h>
1186
+ # include <pthread.h>
1187
+ # include <pthread_np.h>
1188
+
1189
+ #define HAVE_GET_STACK_BASE
1190
+
1191
+ ptr_t GC_get_stack_base ()
1192
+ {
1193
+ stack_t stack ;
1194
+ pthread_stackseg_np (pthread_self (), & stack );
1195
+ return stack .ss_sp ;
1196
+ }
1197
+
1198
+ #endif /* GC_OPENBSD_THREADS */
1199
+
1084
1200
/*
1085
1201
* Register static data segment(s) as roots.
1086
1202
* If more data segments are added later then they need to be registered
@@ -1445,6 +1561,31 @@ int * etext_addr;
1445
1561
1446
1562
#else /* !OS2 && !Windows && !AMIGA */
1447
1563
1564
+ #if defined(OPENBSD )
1565
+
1566
+ /*
1567
+ * Depending on arch alignment there can be multiple holes
1568
+ * between DATASTART & DATAEND. Scan from DATASTART - DATAEND
1569
+ * and register each region.
1570
+ */
1571
+ void GC_register_data_segments (void )
1572
+ {
1573
+ ptr_t region_start , region_end ;
1574
+
1575
+ region_start = DATASTART ;
1576
+
1577
+ for (;;) {
1578
+ region_end = GC_find_limit_openbsd (region_start , DATAEND );
1579
+ GC_add_roots_inner (region_start , region_end , FALSE);
1580
+ if (region_end < DATAEND )
1581
+ region_start = GC_skip_hole_openbsd (region_end , DATAEND );
1582
+ else
1583
+ break ;
1584
+ }
1585
+ }
1586
+
1587
+ # else /* !OS2 && !Windows && !AMIGA && !OPENBSD */
1588
+
1448
1589
void GC_register_data_segments ()
1449
1590
{
1450
1591
# if !defined(PCR ) && !defined(SRC_M3 ) && !defined(MACOS )
@@ -1504,6 +1645,7 @@ void GC_register_data_segments()
1504
1645
/* change. */
1505
1646
}
1506
1647
1648
+ # endif /* ! OPENBSD */
1507
1649
# endif /* ! AMIGA */
1508
1650
# endif /* ! MSWIN32 && ! MSWINCE*/
1509
1651
# endif /* ! OS2 */
0 commit comments