16
16
* BUT ... YOU WERE GOING TO SAY BUT? BUT ...
17
17
* THERE IS NO BUT! DONNY YOU'RE OUT OF YOUR ELEMENT!
18
18
*
19
- * The lock-free data structures implemented here only work because of how
20
- * the Hack phases are synchronized.
19
+ * The lock-free data structures implemented here only work because of how
20
+ * the Hack phases are synchronized.
21
21
*
22
22
* There are 3 kinds of storage implemented in this file.
23
23
* I) The global storage. Used by the master to efficiently transfer a blob
24
- * of data to the workers. This is used to share an environment in
24
+ * of data to the workers. This is used to share an environment in
25
25
* read-only mode with all the workers.
26
26
* The master stores, the workers read.
27
27
*
31
31
*
32
32
* II) The Hashtable.
33
33
* The operations implemented, and their limitations:
34
- *
34
+ *
35
35
* -) Concurrent writes: SUPPORTED
36
- * As long as its not interleaved with any other operation
36
+ * As long as its not interleaved with any other operation
37
37
* (other than mem)!
38
38
*
39
39
* -) Concurrent reads: SUPPORTED
@@ -112,12 +112,12 @@ typedef struct {
112
112
/* The location of the shared memory */
113
113
static char * shared_mem ;
114
114
115
- /* ENCODING: The first element is the size stored in bytes, the rest is
115
+ /* ENCODING: The first element is the size stored in bytes, the rest is
116
116
* the data. The size is set to zero when the storage is empty.
117
117
*/
118
118
static value * global_storage ;
119
119
120
- /* ENCODING:
120
+ /* ENCODING:
121
121
* The highest 2 bits are unused.
122
122
* The next 31 bits encode the key the lower 31 bits the value.
123
123
*/
@@ -223,12 +223,14 @@ static void set_priorities() {
223
223
// at all!)
224
224
//
225
225
// No need to check the return value, if we failed then whatever.
226
+ #ifdef __linux__
226
227
syscall (
227
228
SYS_ioprio_set ,
228
229
IOPRIO_WHO_PROCESS ,
229
230
my_pid ,
230
231
IOPRIO_PRIO_VALUE (IOPRIO_CLASS_IDLE , 7 )
231
232
);
233
+ #endif
232
234
233
235
// Don't slam the CPU either, though this has much less tendency to make the
234
236
// system totally unresponsive so we don't need to lower all the way.
@@ -242,12 +244,12 @@ void hh_shared_init() {
242
244
/* MAP_NORESERVE is because we want a lot more virtual memory than what
243
245
* we are actually going to use.
244
246
*/
245
- int flags = MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE ;
247
+ int flags = MAP_SHARED | MAP_ANON | MAP_NORESERVE ;
246
248
int prot = PROT_READ | PROT_WRITE ;
247
249
248
250
page_size = getpagesize ();
249
251
250
- shared_mem =
252
+ shared_mem =
251
253
(char * )mmap (NULL , page_size + SHARED_MEM_SIZE , prot , flags , 0 , 0 );
252
254
253
255
if (shared_mem == MAP_FAILED ) {
@@ -353,7 +355,7 @@ void hh_shared_clear() {
353
355
* modifying.
354
356
* The table contains key/value bindings encoded in a word.
355
357
* The higher bits represent the key, the lower ones the value.
356
- * Each key/value binding is unique, but a key can have multiple value
358
+ * Each key/value binding is unique, but a key can have multiple value
357
359
* bound to it.
358
360
* Concretely, if you try to add a key/value pair that is already in the table
359
361
* the data structure is left unmodified.
@@ -366,7 +368,7 @@ void hh_add_dep(value ocaml_dep) {
366
368
unsigned long dep = Long_val (ocaml_dep );
367
369
unsigned long hash = dep >> 31 ;
368
370
unsigned long slot = hash & (DEP_SIZE - 1 );
369
-
371
+
370
372
while (1 ) {
371
373
/* It considerably speeds things up to do a normal load before trying using
372
374
* an atomic operation.
@@ -376,7 +378,7 @@ void hh_add_dep(value ocaml_dep) {
376
378
// The binding exists, done!
377
379
if (slot_val == dep )
378
380
return ;
379
-
381
+
380
382
// The slot is free, let's try to take it.
381
383
if (slot_val == 0 ) {
382
384
// See comments in hh_add about its similar construction here.
@@ -400,7 +402,7 @@ value hh_get_dep(value dep) {
400
402
401
403
unsigned long hash = Long_val (dep );
402
404
unsigned long slot = hash & (DEP_SIZE - 1 );
403
-
405
+
404
406
result = Val_int (0 ); // The empty list
405
407
406
408
while (1 ) {
@@ -443,7 +445,7 @@ void hh_call_after_init() {
443
445
*/
444
446
/*****************************************************************************/
445
447
void hh_collect () {
446
- int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE ;
448
+ int flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE ;
447
449
int prot = PROT_READ | PROT_WRITE ;
448
450
char * dest ;
449
451
size_t mem_size = 0 ;
@@ -488,7 +490,7 @@ void hh_collect() {
488
490
489
491
if (munmap (tmp_heap , HEAP_SIZE ) == -1 ) {
490
492
printf ("Error while collecting: %s\n" , strerror (errno ));
491
- exit (2 );
493
+ exit (2 );
492
494
}
493
495
}
494
496
@@ -509,8 +511,8 @@ static char* hh_alloc(size_t size) {
509
511
}
510
512
511
513
/*****************************************************************************/
512
- /* Allocates an ocaml value in the shared heap.
513
- * The values can only be ocaml strings. It returns the address of the
514
+ /* Allocates an ocaml value in the shared heap.
515
+ * The values can only be ocaml strings. It returns the address of the
514
516
* allocated chunk.
515
517
*/
516
518
/*****************************************************************************/
@@ -676,7 +678,7 @@ void hh_move(value key1, value key2) {
676
678
/*****************************************************************************/
677
679
void hh_remove (value key ) {
678
680
unsigned int slot = find_slot (key );
679
-
681
+
680
682
assert (my_pid == master_pid );
681
683
assert (hashtbl [slot ].hash == get_hash (key ));
682
684
hashtbl [slot ].addr = NULL ;
@@ -685,7 +687,7 @@ void hh_remove(value key) {
685
687
/*****************************************************************************/
686
688
/* Returns a copy of the content of a file in an ocaml string.
687
689
* This code should be very tolerant to failure. At any given time, the
688
- * file could be modified, when that happens, we don't want to fail, we
690
+ * file could be modified, when that happens, we don't want to fail, we
689
691
* return the empty string instead.
690
692
*/
691
693
/*****************************************************************************/
@@ -697,7 +699,7 @@ value hh_read_file(value filename) {
697
699
int fd ;
698
700
struct stat sb ;
699
701
char * memblock ;
700
-
702
+
701
703
fd = open (String_val (filename ), O_RDONLY );
702
704
if (fd == -1 ) {
703
705
result = caml_alloc_string (0 );
@@ -706,7 +708,7 @@ value hh_read_file(value filename) {
706
708
result = caml_alloc_string (0 );
707
709
close (fd );
708
710
}
709
- else if ((memblock =
711
+ else if ((memblock =
710
712
(char * )mmap (NULL , sb .st_size , PROT_READ , MAP_PRIVATE , fd , 0 ))
711
713
== MAP_FAILED ) {
712
714
result = caml_alloc_string (0 );
@@ -718,6 +720,6 @@ value hh_read_file(value filename) {
718
720
munmap (memblock , sb .st_size );
719
721
close (fd );
720
722
}
721
-
723
+
722
724
CAMLreturn (result );
723
725
}
0 commit comments