Skip to content

Commit 0e0185e

Browse files
committed
PR12579 (OS-based Synchronisation for Stop-the-World Sections): upstream 51491dd
(cherry picked from commit 20bd57a)
1 parent 5ec597b commit 0e0185e

File tree

13 files changed

+1044
-348
lines changed

13 files changed

+1044
-348
lines changed

ocaml/configure.ac

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,10 @@ AC_CHECK_HEADER([stdatomic.h], [AC_DEFINE([HAS_STDATOMIC_H])])
11461146

11471147
AC_CHECK_HEADER([sys/mman.h], [AC_DEFINE([HAS_SYS_MMAN_H])])
11481148

1149+
AS_CASE([$host],
1150+
[*-*-linux*],
1151+
[AC_CHECK_HEADER([linux/futex.h], [AC_DEFINE([HAS_LINUX_FUTEX_H])])])
1152+
11491153
# Checks for types
11501154

11511155
## off_t
@@ -2766,11 +2770,12 @@ ocamlc_cppflags="$common_cppflags $CPPFLAGS"
27662770

27672771
AS_CASE([$host],
27682772
[*-*-mingw32*],
2769-
[cclibs="$cclibs -lole32 -luuid -lversion"],
2773+
[cclibs="$cclibs -lole32 -luuid -lversion -lshlwapi -lsynchronization"],
27702774
[*-pc-windows],
2771-
[# For whatever reason, flexlink includes -ladvapi32 for mingw-w64, but
2772-
# doesn't include advapi32.lib for MSVC
2773-
cclibs="$cclibs ole32.lib uuid.lib advapi32.lib version.lib"])
2775+
[# For whatever reason, flexlink includes -ladvapi32 and -lshell32 for
2776+
# mingw-w64, but doesn't include advapi32.lib and shell32.lib for MSVC
2777+
cclibs="$cclibs ole32.lib uuid.lib advapi32.lib shell32.lib version.lib \
2778+
shlwapi.lib synchronization.lib"])
27742779

27752780
AC_CONFIG_COMMANDS_PRE([cclibs="$cclibs $mathlib $DLLIBS $PTHREAD_LIBS"])
27762781

ocaml/runtime/caml/domain.h

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,16 @@ Caml_inline intnat caml_domain_alone(void)
101101
int caml_domain_is_in_stw(void);
102102
#endif
103103

104+
int caml_domain_terminating(caml_domain_state *);
105+
int caml_domain_is_terminating(void);
106+
104107
int caml_try_run_on_all_domains_with_spin_work(
105108
int sync,
106109
void (*handler)(caml_domain_state*, void*, int, caml_domain_state**),
107110
void* data,
108111
void (*leader_setup)(caml_domain_state*),
109-
void (*enter_spin_callback)(caml_domain_state*, void*),
112+
/* return nonzero if there may still be useful work to do while spinning */
113+
int (*enter_spin_callback)(caml_domain_state*, void*),
110114
void* enter_spin_data);
111115
int caml_try_run_on_all_domains(
112116
void (*handler)(caml_domain_state*, void*, int, caml_domain_state**),
@@ -167,16 +171,54 @@ int caml_try_run_on_all_domains(
167171
*/
168172

169173

170-
/* barriers */
171-
typedef uintnat barrier_status;
172-
void caml_global_barrier(void);
173-
barrier_status caml_global_barrier_begin(void);
174-
int caml_global_barrier_is_final(barrier_status);
175-
void caml_global_barrier_end(barrier_status);
176-
int caml_global_barrier_num_domains(void);
174+
/* Barriers */
177175

178-
int caml_domain_terminating(caml_domain_state *);
179-
int caml_domain_is_terminating(void);
176+
/* Get the number of parties expected to arrive into the barrier, i.e. the
177+
number of domains participating in the STW section. In most cases the barrier
178+
is used directly from an STW callback that already has the number of
179+
participating domains at hand, which should be used instead. */
180+
int caml_global_barrier_num_participating(void);
181+
182+
/* Unconditionally arrive at the barrier and wait for all parties,
183+
[caml_global_barrier] below should be used instead. */
184+
void caml_enter_global_barrier(int num_participating);
185+
/* Arrive at the barrier and wait iff there is more than one party */
186+
Caml_inline void caml_global_barrier(int num_participating) {
187+
if (num_participating != 1) caml_enter_global_barrier(num_participating);
188+
}
189+
190+
typedef uintnat barrier_status;
191+
/* Arrive at the barrier; if we are the final party, immediately returns a
192+
nonzero value to be passed to [caml_global_barrier_release_as_final]
193+
later, otherwise blocks and returns zero. */
194+
barrier_status caml_global_barrier_and_check_final(int num_participating);
195+
/* Release the barrier with the given status */
196+
void caml_global_barrier_release_as_final(barrier_status status);
197+
/* Arrive at the global barrier and run the body if we are the final party.
198+
Other threads will not be released from the barrier until the final party
199+
finishes executing the body.
200+
201+
Example usage:
202+
203+
Caml_global_barrier_if_final(num_participating) {
204+
do_something_in_final_domain();
205+
}
206+
207+
Note: this expands to an [if] and [for] header, do not exit the body using
208+
jumps or returns, and do not put an [else] immediately after.
209+
*/
210+
#define Caml_global_barrier_if_final(num_participating) \
211+
/* fast path when alone */ \
212+
int CAML_GENSYM(alone) = (num_participating) == 1; \
213+
barrier_status CAML_GENSYM(b) = 0; \
214+
if (CAML_GENSYM(alone) || \
215+
(CAML_GENSYM(b) \
216+
= caml_global_barrier_and_check_final(num_participating))) \
217+
for (int CAML_GENSYM(continue) = 1; CAML_GENSYM(continue); \
218+
/* release the barrier after the body has executed once */ \
219+
((CAML_GENSYM(alone) ? (void)0 : \
220+
caml_global_barrier_release_as_final(CAML_GENSYM(b))), \
221+
CAML_GENSYM(continue) = 0))
180222

181223
#endif /* CAML_INTERNALS */
182224

ocaml/runtime/caml/major_gc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Caml_inline int caml_marking_started(void) {
3131
return caml_gc_phase != Phase_sweep_main;
3232
}
3333

34-
intnat caml_opportunistic_major_work_available (void);
34+
intnat caml_opportunistic_major_work_available (caml_domain_state*);
3535
void caml_opportunistic_major_collection_slice (intnat);
3636
/* auto-triggered slice from within the GC */
3737
#define AUTO_TRIGGERED_MAJOR_SLICE -1

ocaml/runtime/caml/misc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,11 @@ CAMLextern int caml_snwprintf(wchar_t * buf,
595595
# endif
596596
#endif
597597

598+
/* Generate a named symbol that is unique within the current macro expansion */
599+
#define CAML_GENSYM_3(name, l) caml__##name##_##l
600+
#define CAML_GENSYM_2(name, l) CAML_GENSYM_3(name, l)
601+
#define CAML_GENSYM(name) CAML_GENSYM_2(name, __LINE__)
602+
598603
#endif /* CAML_INTERNALS */
599604

600605
/* The [backtrace_slot] type represents values stored in

0 commit comments

Comments
 (0)