Barrier work
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Apr 2009 00:58:47 +0000 (17:58 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Apr 2009 00:58:47 +0000 (17:58 -0700)
Changed barrier to use a counter instead of a mask.

kern/atomic.c
kern/atomic.h
kern/init.c
kern/pmap.c
kern/smp.c
kern/testing.c

index 9e2dd43..d96b190 100644 (file)
@@ -70,37 +70,34 @@ void down_checklist(checklist_t* list)
 }
 
 // byte per cpu, as mentioned below
-void init_barrier_all(barrier_t* cpu_barrier)
+void init_barrier(barrier_t* barrier, uint32_t count)
 {
-       extern uint8_t num_cpus;
-       uint8_t i;
-       cpu_barrier->ready = 0;
-       for(i = 0; i < num_cpus; i++)
-               cpu_barrier->cpu_array[i] = 1;
+       barrier->lock = 0;
+       barrier->init_count = count;
+       barrier->current_count = count;
+       barrier->ready = 0;
+}
+
+void reset_barrier(barrier_t* barrier)
+{
+       barrier->current_count = barrier->init_count;
 }
 
 // primitive barrier function.  all cores call this.
-// consider changing this to use bits and lock bit ops.
-// currently uses a byte per core, and assumes it was 
-// initialized by a core such that num_cpus entries
-// are all 1
-void barrier_all(barrier_t* cpu_barrier)
+void waiton_barrier(barrier_t* barrier)
 {
-       extern uint8_t num_cpus;
-       uint8_t i;
-       uint8_t local_ready = cpu_barrier->ready;
+       uint8_t local_ready = barrier->ready;
 
-       cpu_barrier->cpu_array[lapic_get_id()] = 0;
-       if (lapic_get_id())
-               while(cpu_barrier->ready == local_ready)
+       spin_lock_irqsave(&barrier->lock);
+       barrier->current_count--;
+       if (barrier->current_count) {
+               spin_unlock_irqsave(&barrier->lock);
+               while (barrier->ready == local_ready)
                        cpu_relax();
-       else {
-               for(i = 0; i < num_cpus; i++) {
-                       while(cpu_barrier->cpu_array[i]) 
-                               cpu_relax();
-                       cpu_barrier->cpu_array[i] = 1;
-               }
+       } else {
+               spin_unlock_irqsave(&barrier->lock);
+               reset_barrier(barrier);
                // if we need to wmb(), it'll be here
-               cpu_barrier->ready++;
+               barrier->ready++;
        }
 }
index 32a297e..ee386ae 100644 (file)
@@ -38,26 +38,34 @@ typedef struct checklist {
 #define ZEROS_ARRAY(size)      \
        BUILD_ZEROS_ARRAY_##size
 
+#define DEFAULT_CHECKLIST_MASK(sz) {(sz), ZEROS_ARRAY(sz)}
+#define DEFAULT_CHECKLIST(sz) {0, DEFAULT_CHECKLIST_MASK(sz)}
 #define INIT_CHECKLIST(nm, sz) \
-       checklist_t nm = {0, {(sz), ZEROS_ARRAY(sz)}};
+       checklist_t nm = DEFAULT_CHECKLIST(sz);
 #define INIT_CHECKLIST_MASK(nm, sz)    \
-       checklist_mask_t nm = {(sz), ZEROS_ARRAY(sz)};
+       checklist_mask_t nm = DEFAULT_CHECKLIST_MASK(sz);
 
 int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask);
 int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask);
 int waiton_checklist(checklist_t* list);
 void down_checklist(checklist_t* list);
+// TODO - do we want to adjust the size?
+// TODO - do we want to be able to call waiton without having called commit?
+//     - in the case of protected checklists
 // TODO - want a destroy checklist (when we have kmalloc, or whatever)
 /**************************************************************/
 
 /* Barrier: currently made for everyone barriering.  Change to use checklist */
 typedef struct barrier {
-       volatile uint8_t COUNT(MAX_NUM_CPUS) cpu_array[MAX_NUM_CPUS]; 
+       volatile uint32_t lock;
+       uint32_t init_count;
+       uint32_t current_count;
     volatile uint8_t ready;
-       } barrier_t;
+} barrier_t;
 
-void init_barrier_all(barrier_t* cpu_barrier);
-void barrier_all(barrier_t* cpu_barrier);
+void init_barrier(barrier_t* barrier, uint32_t count);
+void reset_barrier(barrier_t* barrier);
+void waiton_barrier(barrier_t* barrier);
 
 /* Inlined functions declared above */
 static inline void spin_lock(volatile uint32_t* lock)
index b8abd67..3c95888 100644 (file)
@@ -51,9 +51,10 @@ void kernel_init(multiboot_info_t *mboot_info)
 
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
-
-       panic("Don't Panic");
+       test_checklists();
        test_barrier();
+       panic("Don't Panic");
+
        test_print_info();
        test_ipi_sending();
 
index e989580..a73cc50 100644 (file)
@@ -277,7 +277,7 @@ void setup_default_mtrrs(barrier_t* smp_barrier)
        // barrier - if we're meant to do this for all cores, we'll be 
        // passed a pointer to an initialized barrier
        if (smp_barrier)
-               barrier_all(smp_barrier);
+               waiton_barrier(smp_barrier);
        
        // disable caching      cr0: set CD and clear NW
        lcr0((rcr0() | CR0_CD) & ~CR0_NW);
@@ -318,7 +318,7 @@ void setup_default_mtrrs(barrier_t* smp_barrier)
        lcr0(rcr0() & ~(CR0_CD | CR0_NW));
        // barrier
        if (smp_barrier)
-               barrier_all(smp_barrier);
+               waiton_barrier(smp_barrier);
        // enable interrupts
        enable_irqsave(&state);
 }
index 3f53e65..9adb47e 100644 (file)
@@ -107,7 +107,7 @@ void smp_boot(void)
        page_decref(smp_stack);
 
        // Set up all cores to use the proper MTRRs
-       init_barrier_all(&generic_barrier); // barrier used by smp_mtrr_handler
+       init_barrier(&generic_barrier, num_cpus); // barrier used by smp_mtrr_handler
        smp_call_function_all(smp_mtrr_handler, 0);
 
        // Should probably flush everyone's TLB at this point, to get rid of 
index a2e9d8c..3919c11 100644 (file)
@@ -93,12 +93,13 @@ void test_print_info(void)
 }
        
 
+extern uint8_t num_cpus;
 barrier_t test_cpu_array;
 
 void test_barrier(void)
 {
        cprintf("Core 0 initializing barrier\n");
-       init_barrier_all(&test_cpu_array);
+       init_barrier(&test_cpu_array, num_cpus);
        cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
        smp_call_function_all(test_barrier_handler, 0);
 }
@@ -312,14 +313,14 @@ void test_print_info_handler(struct Trapframe *tf)
 void test_barrier_handler(struct Trapframe *tf)
 {
        cprintf("Round 1: Core %d\n", lapic_get_id());
-       barrier_all(&test_cpu_array);
-       barrier_all(&test_cpu_array);
-       barrier_all(&test_cpu_array);
-       barrier_all(&test_cpu_array);
-       barrier_all(&test_cpu_array);
-       barrier_all(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
        cprintf("Round 2: Core %d\n", lapic_get_id());
-       barrier_all(&test_cpu_array);
+       waiton_barrier(&test_cpu_array);
        cprintf("Round 3: Core %d\n", lapic_get_id());
        // uncomment to see it fucked up
        //cprintf("Round 4: Core %d\n", lapic_get_id());