smp_call wait / backend work
[akaros.git] / kern / atomic.c
index 9e2dd43..4ac337c 100644 (file)
@@ -13,7 +13,7 @@ int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask)
        // wait til the list is available.  could have some adaptive thing here
        // where it fails after X tries (like 500), gives up the lock, and returns
        // an error code
-       while (!(BITMASK_IS_CLEAR(list->mask.bits, list->mask.size)))
+       while (!checklist_is_clear(list))
                cpu_relax();
 
        // list is ours and clear, set it to the settings of our list
@@ -57,50 +57,66 @@ int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask)
 int waiton_checklist(checklist_t* list)
 {
        // can consider breakout out early, like above, and erroring out
-       while (!(BITMASK_IS_CLEAR(list->mask.bits, list->mask.size)))
+       while (!checklist_is_clear(list))
                cpu_relax();
        spin_unlock_irqsave(&list->lock);
        return 0;
 }
 
+// peaks in and sees if the list is locked with it's spinlock
+int checklist_is_locked(checklist_t* list)
+{
+       // remember the lock status is the lowest byte of the lock
+       return list->lock & 0xff;
+}
+
+// no synch guarantees - just looks at the list
+int checklist_is_clear(checklist_t* list)
+{
+       return BITMASK_IS_CLEAR(list->mask.bits, list->mask.size);
+}
+
+// no synch guarantees - just resets the list to empty
+void reset_checklist(checklist_t* list)
+{
+       CLR_BITMASK(list->mask.bits, list->mask.size);
+}
+
 // CPU mask specific - this is how cores report in
 void down_checklist(checklist_t* list)
 {
        CLR_BITMASK_BIT_ATOMIC(list->mask.bits, lapic_get_id());
 }
 
-// byte per cpu, as mentioned below
-void init_barrier_all(barrier_t* cpu_barrier)
+/* Barriers */
+void init_barrier(barrier_t* barrier, uint32_t count)
+{
+       barrier->lock = 0;
+       barrier->init_count = count;
+       barrier->current_count = count;
+       barrier->ready = 0;
+}
+
+void reset_barrier(barrier_t* barrier)
 {
-       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->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++;
        }
 }