Fix: handle sys_futex() FUTEX_WAIT interrupted by signal
[urcu.git] / rculfhash.c
index 2a450459f5cfa50e94bce03e00be0ad1be7b2b4f..454001d1f7cab6fe51340d7c71db398aa17bce0b 100644 (file)
@@ -426,7 +426,7 @@ unsigned int fls_u32(uint32_t x)
 {
        int r;
 
-       asm("bsrl %1,%0\n\t"
+       __asm__ ("bsrl %1,%0\n\t"
            "jnz 1f\n\t"
            "movl $-1,%0\n\t"
            "1:\n\t"
@@ -442,7 +442,7 @@ unsigned int fls_u64(uint64_t x)
 {
        long r;
 
-       asm("bsrq %1,%0\n\t"
+       __asm__ ("bsrq %1,%0\n\t"
            "jnz 1f\n\t"
            "movq $-1,%0\n\t"
            "1:\n\t"
@@ -1171,11 +1171,15 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
                void (*fct)(struct cds_lfht *ht, unsigned long i,
                        unsigned long start, unsigned long len))
 {
-       unsigned long partition_len;
+       unsigned long partition_len, start = 0;
        struct partition_resize_work *work;
        int thread, ret;
        unsigned long nr_threads;
 
+       assert(nr_cpus_mask != -1);
+       if (nr_cpus_mask < 0 || len < 2 * MIN_PARTITION_PER_THREAD)
+               goto fallback;
+
        /*
         * Note: nr_cpus_mask + 1 is always power of 2.
         * We spawn just the number of threads we need to satisfy the minimum
@@ -1201,6 +1205,17 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
                work[thread].fct = fct;
                ret = pthread_create(&(work[thread].thread_id), ht->resize_attr,
                        partition_resize_thread, &work[thread]);
+               if (ret == EAGAIN) {
+                       /*
+                        * Out of resources: wait and join the threads
+                        * we've created, then handle leftovers.
+                        */
+                       dbg_printf("error spawning for resize, single-threading\n");
+                       start = work[thread].start;
+                       len -= start;
+                       nr_threads = thread;
+                       break;
+               }
                assert(!ret);
        }
        for (thread = 0; thread < nr_threads; thread++) {
@@ -1208,10 +1223,17 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
                assert(!ret);
        }
        free(work);
-       return;
+
+       /*
+        * A pthread_create failure above will either lead in us having
+        * no threads to join or starting at a non-zero offset,
+        * fallback to single thread processing of leftovers.
+        */
+       if (start == 0 && nr_threads > 0)
+               return;
 fallback:
        ht->flavor->thread_online();
-       fct(ht, i, 0, len);
+       fct(ht, i, start, len);
        ht->flavor->thread_offline();
 }
 
@@ -1250,13 +1272,6 @@ static
 void init_table_populate(struct cds_lfht *ht, unsigned long i,
                         unsigned long len)
 {
-       assert(nr_cpus_mask != -1);
-       if (nr_cpus_mask < 0 || len < 2 * MIN_PARTITION_PER_THREAD) {
-               ht->flavor->thread_online();
-               init_table_populate_partition(ht, i, 0, len);
-               ht->flavor->thread_offline();
-               return;
-       }
        partition_resize_helper(ht, i, len, init_table_populate_partition);
 }
 
@@ -1349,14 +1364,6 @@ void remove_table_partition(struct cds_lfht *ht, unsigned long i,
 static
 void remove_table(struct cds_lfht *ht, unsigned long i, unsigned long len)
 {
-
-       assert(nr_cpus_mask != -1);
-       if (nr_cpus_mask < 0 || len < 2 * MIN_PARTITION_PER_THREAD) {
-               ht->flavor->thread_online();
-               remove_table_partition(ht, i, 0, len);
-               ht->flavor->thread_offline();
-               return;
-       }
        partition_resize_helper(ht, i, len, remove_table_partition);
 }
 
This page took 0.023643 seconds and 4 git commands to generate.