The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #13593 from NickBarnes/nick-atomic-counter

Unify separate atomic counter functions in runtime

authored by

Gabriel Scherer and committed by
GitHub
2ec92796 718a664b

+106 -112
+1 -1
otherlibs/unix/mmap_ba.c
··· 33 33 if (b->proxy == NULL) { 34 34 caml_ba_unmap_file(b->data, caml_ba_byte_size(b)); 35 35 } else { 36 - if (-- b->proxy->refcount == 0) { 36 + if (caml_atomic_counter_decr(&b->proxy->refcount) == 0) { 37 37 caml_ba_unmap_file(b->proxy->data, b->proxy->size); 38 38 free(b->proxy); 39 39 }
+4 -4
runtime/bigarray.c
··· 28 28 #include "caml/memory.h" 29 29 #include "caml/mlvalues.h" 30 30 #include "caml/signals.h" 31 - #include "caml/atomic_refcount.h" 31 + #include "caml/camlatomic.h" 32 32 33 33 #define int8 caml_ba_int8 34 34 #define uint8 caml_ba_uint8 ··· 292 292 if (b->proxy == NULL) { 293 293 free(b->data); 294 294 } else { 295 - if (caml_atomic_refcount_decr(&b->proxy->refcount) == 1) { 295 + if (caml_atomic_counter_decr(&b->proxy->refcount) == 0) { 296 296 free(b->proxy->data); 297 297 free(b->proxy); 298 298 } ··· 1077 1077 /* If b1 is already a proxy for a larger array, increment refcount of 1078 1078 proxy */ 1079 1079 b2->proxy = b1->proxy; 1080 - caml_atomic_refcount_incr(&b1->proxy->refcount); 1080 + (void)caml_atomic_counter_incr(&b1->proxy->refcount); 1081 1081 } else { 1082 1082 /* Otherwise, create proxy and attach it to both b1 and b2 */ 1083 1083 proxy = malloc(sizeof(struct caml_ba_proxy)); 1084 1084 if (proxy == NULL) caml_raise_out_of_memory(); 1085 - caml_atomic_refcount_init(&proxy->refcount, 2); 1085 + caml_atomic_counter_init(&proxy->refcount, 2); 1086 1086 /* initial refcount: 2 = original array + sub array */ 1087 1087 proxy->data = b1->data; 1088 1088 proxy->size =
-37
runtime/caml/atomic_refcount.h
··· 1 - /**************************************************************************/ 2 - /* */ 3 - /* OCaml */ 4 - /* */ 5 - /* Florian Angeletti, projet Cambium, Inria */ 6 - /* */ 7 - /* Copyright 2022 Institut National de Recherche en Informatique et */ 8 - /* en Automatique. */ 9 - /* */ 10 - /* All rights reserved. This file is distributed under the terms of */ 11 - /* the GNU Lesser General Public License version 2.1, with the */ 12 - /* special exception on linking described in the file LICENSE. */ 13 - /* */ 14 - /**************************************************************************/ 15 - 16 - #ifndef CAML_ATOMIC_REFCOUNT_H 17 - #define CAML_ATOMIC_REFCOUNT_H 18 - 19 - #ifdef CAML_INTERNALS 20 - 21 - #include "camlatomic.h" 22 - 23 - Caml_inline void caml_atomic_refcount_init(atomic_uintnat* refc, uintnat n){ 24 - atomic_store_release(refc, n); 25 - } 26 - 27 - Caml_inline uintnat caml_atomic_refcount_decr(atomic_uintnat* refcount){ 28 - return atomic_fetch_add (refcount, -1); 29 - } 30 - 31 - Caml_inline uintnat caml_atomic_refcount_incr(atomic_uintnat* refcount){ 32 - return atomic_fetch_add (refcount, 1); 33 - } 34 - 35 - #endif /* CAML_INTERNALS */ 36 - 37 - #endif // CAML_ATOMIC_REFCOUNT_H
+1
runtime/caml/bigarray.h
··· 18 18 19 19 #include "config.h" 20 20 #include "mlvalues.h" 21 + #include "camlatomic.h" 21 22 22 23 typedef signed char caml_ba_int8; 23 24 typedef unsigned char caml_ba_uint8;
+35
runtime/caml/camlatomic.h
··· 17 17 #define CAML_ATOMIC_H 18 18 19 19 #include "config.h" 20 + #include "misc.h" 20 21 21 22 /* 22 23 * C11 atomics types and utility macros. ··· 55 56 atomic_store_explicit((p), (v), memory_order_release) 56 57 #define atomic_store_relaxed(p, v) \ 57 58 atomic_store_explicit((p), (v), memory_order_relaxed) 59 + 60 + /* Atomic counters, abstracted here for use across the runtime. */ 61 + 62 + Caml_inline void caml_atomic_counter_init(atomic_uintnat* counter, uintnat n) 63 + { 64 + atomic_store_release(counter, n); 65 + } 66 + 67 + /* Atomically get the current value of an atomic uintnat counter */ 68 + 69 + Caml_inline uintnat caml_atomic_counter_value(atomic_uintnat* counter) 70 + { 71 + return atomic_load_acquire(counter); 72 + } 73 + 74 + /* Decrement an atomic uintnat counter. Assertion check for 75 + * underflow. Returns the new value. */ 76 + 77 + Caml_inline uintnat caml_atomic_counter_decr(atomic_uintnat* counter) 78 + { 79 + uintnat old = atomic_fetch_sub(counter, 1); 80 + CAMLassert (old > 0); 81 + return old-1; 82 + } 83 + 84 + /* Increment an atomic uintnat counter. Assertion check for 85 + * overflow. Returns the new value. */ 86 + 87 + Caml_inline uintnat caml_atomic_counter_incr(atomic_uintnat* counter) 88 + { 89 + uintnat old = atomic_fetch_add(counter, 1); 90 + CAMLassert (old+1 != 0); 91 + return old+1; 92 + } 58 93 59 94 #endif /* CAML_INTERNALS */ 60 95
+3 -3
runtime/caml/misc.h
··· 27 27 #include <stdarg.h> 28 28 #include <limits.h> 29 29 30 - #include "camlatomic.h" 31 - 32 30 /* Detection of available C attributes and compiler extensions */ 33 31 34 32 #ifndef __has_c_attribute ··· 289 287 can obtain the domain id with Caml_state->id. These functions must 290 288 be reentrant. */ 291 289 #ifndef __cplusplus 290 + #include <stdatomic.h> 291 + 292 292 typedef void (*caml_timing_hook) (void); 293 293 extern _Atomic caml_timing_hook caml_major_slice_begin_hook; 294 294 extern _Atomic caml_timing_hook caml_major_slice_end_hook; ··· 615 615 616 616 /* runtime message flags. Settable with v= in OCAMLRUNPARAM */ 617 617 618 - extern atomic_uintnat caml_verb_gc; 618 + extern _Atomic uintnat caml_verb_gc; 619 619 620 620 /* Bits which may be set in caml_verb_gc. The quotations are from the 621 621 * OCaml manual. */
+1
runtime/caml/mlvalues.h
··· 19 19 #include "config.h" 20 20 #include "misc.h" 21 21 #include "tsan.h" 22 + #include "camlatomic.h" 22 23 23 24 #ifdef __cplusplus 24 25 extern "C" {
-8
runtime/caml/platform.h
··· 65 65 } 66 66 67 67 68 - /* Atomic read-modify-write instructions, with full fences */ 69 - 70 - Caml_inline uintnat atomic_fetch_add_verify_ge0(atomic_uintnat* p, intnat v) { 71 - uintnat result = atomic_fetch_add(p,v); 72 - CAMLassert ((intnat)result > 0); 73 - return result; 74 - } 75 - 76 68 /* Warning: blocking functions. 77 69 78 70 Blocking functions are for use in the runtime outside of the
+61 -59
runtime/major_gc.c
··· 296 296 { 297 297 caml_plat_lock_blocking(&ephe_lock); 298 298 299 - atomic_fetch_add(&ephe_cycle_info.ephe_cycle, +1); 300 - CAMLassert(atomic_load_acquire(&ephe_cycle_info.num_domains_done) <= 301 - atomic_load_acquire(&ephe_cycle_info.num_domains_todo)); 302 - atomic_store(&ephe_cycle_info.num_domains_done, 0); 299 + (void)caml_atomic_counter_incr(&ephe_cycle_info.ephe_cycle); 300 + CAMLassert(caml_atomic_counter_value(&ephe_cycle_info.num_domains_done) <= 301 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo)); 302 + caml_atomic_counter_init(&ephe_cycle_info.num_domains_done, 0); 303 303 304 304 caml_plat_unlock(&ephe_lock); 305 305 } ··· 311 311 /* Force next ephemeron marking cycle in order to avoid reasoning about 312 312 * whether the domain has already incremented 313 313 * [ephe_cycle_info.num_domains_done] counter. */ 314 - atomic_store(&ephe_cycle_info.num_domains_done, 0); 315 - atomic_fetch_add(&ephe_cycle_info.ephe_cycle, +1); 314 + caml_atomic_counter_init(&ephe_cycle_info.num_domains_done, 0); 315 + (void)caml_atomic_counter_incr(&ephe_cycle_info.ephe_cycle); 316 316 317 317 /* Since the todo list is empty, this domain does not need to participate in 318 318 * further ephemeron cycles. */ 319 - atomic_fetch_sub(&ephe_cycle_info.num_domains_todo, 1); 320 - CAMLassert(atomic_load_acquire(&ephe_cycle_info.num_domains_done) <= 321 - atomic_load_acquire(&ephe_cycle_info.num_domains_todo)); 319 + (void)caml_atomic_counter_decr(&ephe_cycle_info.num_domains_todo); 320 + CAMLassert(caml_atomic_counter_value(&ephe_cycle_info.num_domains_done) <= 321 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo)); 322 322 323 323 caml_plat_unlock(&ephe_lock); 324 324 } ··· 326 326 /* Record that ephemeron marking was done for the given ephemeron cycle. */ 327 327 static void record_ephe_marking_done (uintnat ephe_cycle) 328 328 { 329 - CAMLassert (ephe_cycle <= atomic_load_acquire(&ephe_cycle_info.ephe_cycle)); 329 + CAMLassert (ephe_cycle <= 330 + caml_atomic_counter_value(&ephe_cycle_info.ephe_cycle)); 330 331 CAMLassert (Caml_state->marking_done); 331 332 332 - if (ephe_cycle < atomic_load_acquire(&ephe_cycle_info.ephe_cycle)) 333 + if (ephe_cycle < caml_atomic_counter_value(&ephe_cycle_info.ephe_cycle)) 333 334 return; 334 335 335 336 caml_plat_lock_blocking(&ephe_lock); 336 - if (ephe_cycle == atomic_load(&ephe_cycle_info.ephe_cycle)) { 337 + if (ephe_cycle == caml_atomic_counter_value(&ephe_cycle_info.ephe_cycle)) { 337 338 Caml_state->ephe_info->cycle = ephe_cycle; 338 - atomic_fetch_add(&ephe_cycle_info.num_domains_done, +1); 339 - CAMLassert(atomic_load_acquire(&ephe_cycle_info.num_domains_done) <= 340 - atomic_load_acquire(&ephe_cycle_info.num_domains_todo)); 339 + (void)caml_atomic_counter_incr(&ephe_cycle_info.num_domains_done); 340 + CAMLassert(caml_atomic_counter_value(&ephe_cycle_info.num_domains_done) <= 341 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo)); 341 342 } 342 343 caml_plat_unlock(&ephe_lock); 343 344 } ··· 424 425 425 426 if (ephe_info->must_sweep_ephe) { 426 427 ephe_info->must_sweep_ephe = 0; 427 - atomic_fetch_add_verify_ge0(&num_domains_to_ephe_sweep, -1); 428 + (void)caml_atomic_counter_decr(&num_domains_to_ephe_sweep); 428 429 } 429 430 CAMLassert (ephe_info->must_sweep_ephe == 0); 430 431 CAMLassert (ephe_info->live == 0); ··· 437 438 438 439 if (f->todo_head != NULL || f->first.size != 0 || f->last.size != 0) { 439 440 /* have some final structures */ 440 - atomic_fetch_add(&num_domains_orphaning_finalisers, +1); 441 + (void)caml_atomic_counter_incr(&num_domains_orphaning_finalisers); 441 442 if (caml_gc_phase != Phase_sweep_and_mark_main) { 442 443 /* Force a major GC cycle to simplify constraints for orphaning 443 444 finalisers. See note attached to the declaration of ··· 456 457 457 458 /* Create a dummy final info */ 458 459 f = domain_state->final_info = caml_alloc_final_info(); 459 - atomic_fetch_add_verify_ge0(&num_domains_orphaning_finalisers, -1); 460 + (void)caml_atomic_counter_decr(&num_domains_orphaning_finalisers); 460 461 } 461 462 462 463 /* [caml_orphan_finalisers] is called in a while loop in ··· 464 465 We take care to decrement the [num_domains_to_final_update*] counters only 465 466 if we have not already decremented it for the current cycle. */ 466 467 if(!f->updated_first) { 467 - atomic_fetch_add_verify_ge0(&num_domains_to_final_update_first, -1); 468 + (void)caml_atomic_counter_decr(&num_domains_to_final_update_first); 468 469 f->updated_first = 1; 469 470 } 470 471 if(!f->updated_last) { 471 - atomic_fetch_add_verify_ge0(&num_domains_to_final_update_last, -1); 472 + (void)caml_atomic_counter_decr(&num_domains_to_final_update_last); 472 473 f->updated_last = 1; 473 474 } 474 475 } ··· 1152 1153 } else { 1153 1154 ephe_next_cycle (); 1154 1155 domain_state->marking_done = 1; 1155 - atomic_fetch_add_verify_ge0(&num_domains_to_mark, -1); 1156 + (void)caml_atomic_counter_decr(&num_domains_to_mark); 1156 1157 } 1157 1158 } 1158 1159 } ··· 1203 1204 if (Has_status_hd(hd, caml_global_heap_state.UNMARKED)) { 1204 1205 caml_domain_state* domain_state = (caml_domain_state*)state; 1205 1206 if (domain_state->marking_done) { 1206 - atomic_fetch_add(&num_domains_to_mark, 1); 1207 + (void)caml_atomic_counter_incr(&num_domains_to_mark); 1207 1208 domain_state->marking_done = 0; 1208 1209 } 1209 1210 if (Tag_hd(hd) == Cont_tag) { ··· 1389 1390 1390 1391 domain->swept_words = 0; 1391 1392 1392 - atomic_store_release(&num_domains_to_sweep, num_domains_in_stw); 1393 - atomic_store_release(&num_domains_to_mark, num_domains_in_stw); 1393 + caml_atomic_counter_init(&num_domains_to_sweep, num_domains_in_stw); 1394 + caml_atomic_counter_init(&num_domains_to_mark, num_domains_in_stw); 1394 1395 1395 1396 caml_gc_phase = Phase_sweep_and_mark_main; 1396 - atomic_store(&ephe_cycle_info.num_domains_todo, num_domains_in_stw); 1397 - atomic_store(&ephe_cycle_info.ephe_cycle, 1); 1398 - atomic_store(&ephe_cycle_info.num_domains_done, 0); 1397 + caml_atomic_counter_init(&ephe_cycle_info.num_domains_todo, 1398 + num_domains_in_stw); 1399 + caml_atomic_counter_init(&ephe_cycle_info.ephe_cycle, 1); 1400 + caml_atomic_counter_init(&ephe_cycle_info.num_domains_done, 0); 1399 1401 1400 - atomic_store_release(&num_domains_to_ephe_sweep, 0); 1402 + caml_atomic_counter_init(&num_domains_to_ephe_sweep, 0); 1401 1403 /* Will be set to the correct number when switching to 1402 1404 [Phase_sweep_ephe] */ 1403 1405 1404 - atomic_store_release(&num_domains_to_final_update_first, 1405 - num_domains_in_stw); 1406 - atomic_store_release(&num_domains_to_final_update_last, 1407 - num_domains_in_stw); 1406 + caml_atomic_counter_init(&num_domains_to_final_update_first, 1407 + num_domains_in_stw); 1408 + caml_atomic_counter_init(&num_domains_to_final_update_last, 1409 + num_domains_in_stw); 1408 1410 1409 1411 atomic_store(&domain_global_roots_started, WORK_UNSTARTED); 1410 1412 ··· 1437 1439 CAML_EV_BEGIN(EV_MAJOR_GC_CYCLE_DOMAINS); 1438 1440 1439 1441 CAMLassert(domain == Caml_state); 1440 - CAMLassert(atomic_load_acquire(&ephe_cycle_info.num_domains_todo) == 1441 - atomic_load_acquire(&ephe_cycle_info.num_domains_done)); 1442 - CAMLassert(atomic_load(&num_domains_to_mark) == 0); 1443 - CAMLassert(atomic_load(&num_domains_to_sweep) == 0); 1444 - CAMLassert(atomic_load(&num_domains_to_ephe_sweep) == 0); 1442 + CAMLassert(caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo) == 1443 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_done)); 1444 + CAMLassert(caml_atomic_counter_value(&num_domains_to_mark) == 0); 1445 + CAMLassert(caml_atomic_counter_value(&num_domains_to_sweep) == 0); 1446 + CAMLassert(caml_atomic_counter_value(&num_domains_to_ephe_sweep) == 0); 1445 1447 1446 1448 caml_empty_minor_heap_no_major_slice_from_stw 1447 1449 (domain, (void*)0, participating_count, participating); ··· 1517 1519 !caml_addrmap_iter_ok(&domain->mark_stack->compressed_stack, 1518 1520 domain->mark_stack->compressed_stack_iter) 1519 1521 ) { 1520 - atomic_fetch_add_verify_ge0(&num_domains_to_mark, -1); 1522 + (void)caml_atomic_counter_decr(&num_domains_to_mark); 1521 1523 domain->marking_done = 1; 1522 1524 } 1523 1525 ··· 1561 1563 return 1562 1564 /* Marking is done */ 1563 1565 caml_gc_phase == Phase_sweep_and_mark_main && 1564 - atomic_load_acquire (&num_domains_to_sweep) == 0 && 1565 - atomic_load_acquire (&num_domains_to_mark) == 0 && 1566 + caml_atomic_counter_value (&num_domains_to_sweep) == 0 && 1567 + caml_atomic_counter_value (&num_domains_to_mark) == 0 && 1566 1568 1567 1569 /* No domains are orphaning finalisers. */ 1568 - atomic_load_acquire (&num_domains_orphaning_finalisers) == 0 && 1570 + caml_atomic_counter_value (&num_domains_orphaning_finalisers) == 0 && 1569 1571 1570 1572 /* Ephemeron marking is done */ 1571 - atomic_load_acquire(&ephe_cycle_info.num_domains_todo) == 1572 - atomic_load_acquire(&ephe_cycle_info.num_domains_done) && 1573 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo) == 1574 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_done) && 1573 1575 1574 1576 /* All orphaned ephemerons have been adopted */ 1575 1577 no_orphaned_work(); ··· 1580 1582 return 1581 1583 /* updated finalise first values */ 1582 1584 caml_gc_phase == Phase_mark_final && 1583 - atomic_load_acquire (&num_domains_to_final_update_first) == 0 && 1585 + caml_atomic_counter_value (&num_domains_to_final_update_first) == 0 && 1584 1586 1585 1587 /* Marking is done */ 1586 - atomic_load_acquire (&num_domains_to_mark) == 0 && 1588 + caml_atomic_counter_value (&num_domains_to_mark) == 0 && 1587 1589 1588 1590 /* Ephemeron marking is done */ 1589 - atomic_load_acquire(&ephe_cycle_info.num_domains_todo) == 1590 - atomic_load_acquire(&ephe_cycle_info.num_domains_done) && 1591 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_todo) == 1592 + caml_atomic_counter_value(&ephe_cycle_info.num_domains_done) && 1591 1593 1592 1594 /* All orphaned ephemerons have been adopted */ 1593 1595 no_orphaned_work(); ··· 1598 1600 return 1599 1601 /* All domains have swept their ephemerons */ 1600 1602 caml_gc_phase == Phase_sweep_ephe && 1601 - atomic_load_acquire (&num_domains_to_ephe_sweep) == 0 && 1603 + caml_atomic_counter_value (&num_domains_to_ephe_sweep) == 0 && 1602 1604 1603 1605 /* All domains have updated finalise last values */ 1604 - atomic_load_acquire (&num_domains_to_final_update_last) == 0 && 1606 + caml_atomic_counter_value (&num_domains_to_final_update_last) == 0 && 1605 1607 1606 1608 /* All orphaned structures have been adopted */ 1607 1609 no_orphaned_work(); ··· 1619 1621 caml_gc_phase = Phase_mark_final; 1620 1622 } else if (is_complete_phase_mark_final()) { 1621 1623 caml_gc_phase = Phase_sweep_ephe; 1622 - atomic_store_release(&num_domains_to_ephe_sweep, participant_count); 1624 + caml_atomic_counter_init(&num_domains_to_ephe_sweep, participant_count); 1623 1625 for (int i = 0; i < participant_count; i++) 1624 1626 participating[i]->ephe_info->must_sweep_ephe = 1; 1625 1627 } ··· 1696 1698 commit_major_slice_work (work_done); 1697 1699 if (work_done == 0) { 1698 1700 domain_state->sweeping_done = 1; 1699 - atomic_fetch_add_verify_ge0(&num_domains_to_sweep, -1); 1701 + (void)caml_atomic_counter_decr(&num_domains_to_sweep); 1700 1702 } 1701 1703 } 1702 1704 ··· 1725 1727 get_major_slice_work(mode) > 0 && 1726 1728 caml_final_update_first(domain_state)) { 1727 1729 /* This domain has updated finalise first values */ 1728 - atomic_fetch_add_verify_ge0(&num_domains_to_final_update_first, -1); 1730 + (void)caml_atomic_counter_decr(&num_domains_to_final_update_first); 1729 1731 if (!domain_state->marking_done && 1730 1732 get_major_slice_work(mode) > 0) 1731 1733 goto mark_again; ··· 1735 1737 get_major_slice_work(mode) > 0 && 1736 1738 caml_final_update_last(domain_state)) { 1737 1739 /* This domain has updated finalise last values */ 1738 - atomic_fetch_add_verify_ge0(&num_domains_to_final_update_last, -1); 1740 + (void)caml_atomic_counter_decr(&num_domains_to_final_update_last); 1739 1741 /* Nothing has been marked while updating last */ 1740 1742 } 1741 1743 ··· 1747 1749 /* Ephemerons */ 1748 1750 if (caml_gc_phase != Phase_sweep_ephe) { 1749 1751 /* Ephemeron Marking */ 1750 - saved_ephe_cycle = atomic_load_acquire(&ephe_cycle_info.ephe_cycle); 1752 + saved_ephe_cycle = caml_atomic_counter_value(&ephe_cycle_info.ephe_cycle); 1751 1753 if (domain_state->ephe_info->todo != (value) NULL && 1752 1754 saved_ephe_cycle > domain_state->ephe_info->cycle && 1753 1755 get_major_slice_work(mode) > 0) { ··· 1805 1807 /* If the todo list is empty, then the ephemeron has no sweeping work 1806 1808 * to do. */ 1807 1809 if (domain_state->ephe_info->todo == 0) { 1808 - atomic_fetch_add_verify_ge0(&num_domains_to_ephe_sweep, -1); 1810 + (void)caml_atomic_counter_decr(&num_domains_to_ephe_sweep); 1809 1811 } 1810 1812 } 1811 1813 ··· 1823 1825 1824 1826 CAML_EV_END(EV_MAJOR_EPHE_SWEEP); 1825 1827 if (domain_state->ephe_info->todo == 0) { 1826 - atomic_fetch_add_verify_ge0(&num_domains_to_ephe_sweep, -1); 1828 + (void)caml_atomic_counter_decr(&num_domains_to_ephe_sweep); 1827 1829 } 1828 1830 } 1829 1831 } ··· 2000 2002 /* just finished sweeping */ 2001 2003 CAMLassert(Caml_state->sweeping_done == 0); 2002 2004 Caml_state->sweeping_done = 1; 2003 - atomic_fetch_add_verify_ge0(&num_domains_to_sweep, -1); 2005 + (void)caml_atomic_counter_decr(&num_domains_to_sweep); 2004 2006 break; 2005 2007 } 2006 2008 caml_handle_incoming_interrupts(); ··· 2120 2122 d->mark_stack = NULL; 2121 2123 return -1; 2122 2124 } 2123 - atomic_fetch_add(&num_domains_to_final_update_first, 1); 2124 - atomic_fetch_add(&num_domains_to_final_update_last, 1); 2125 + (void)caml_atomic_counter_incr(&num_domains_to_final_update_first); 2126 + (void)caml_atomic_counter_incr(&num_domains_to_final_update_last); 2125 2127 2126 2128 return 0; 2127 2129 }