return 0;
}
-
-/* Barrier synchronization primitive
- * -- This call will block until all the guest cores are waiting at a common synchronization point
- * in a yield loop. The core will block at the sync point until the barrier is lowered.
- *
- * ARGUMENTS:
- * vm_info -- The VM for which the barrier is being activated
- * local_core -- The core whose thread this function is being called from, or NULL
- * if the calling thread is not associated with a VM's core context
- */
-
-int v3_raise_barrier(struct v3_vm_info * vm_info, struct guest_info * local_core) {
+int v3_raise_barrier_nowait(struct v3_vm_info * vm_info, struct guest_info * local_core) {
struct v3_barrier * barrier = &(vm_info->barrier);
addr_t flag;
int acquired = 0;
- int all_blocked = 0;
int local_vcpu = -1;
int i = 0;
-
-
flag = v3_lock_irqsave(barrier->lock);
if (barrier->active == 0) {
}
}
+ return 0;
+}
+
+int v3_wait_for_barrier(struct v3_vm_info * vm_info, struct guest_info * local_core) {
+ struct v3_barrier * barrier = &(vm_info->barrier);
+ int all_blocked = 0;
+ int i = 0;
+
+ if (barrier->active == 0) {
+ return -1;
+ }
+
// wait for barrier catch on all cores
while (all_blocked == 0) {
all_blocked = 1;
for (i = 0; i < vm_info->num_cores; i++) {
+
+ // Tricky: If a core is not running then it is safe to ignore it.
+ // Whenever we transition a core to the RUNNING state we MUST immediately wait on the barrier.
+ // TODO: Wrap the state transitions in functions that do this automatically
+ if (vm_info->cores[i].core_run_state != CORE_RUNNING) {
+ continue;
+ }
+
if (v3_bitmap_check(&(barrier->cpu_map), i) == 0) {
// There is still a core that is not waiting at the barrier
all_blocked = 0;
break;
}
- v3_yield(local_core);
+ v3_yield(local_core,-1);
}
-
return 0;
}
+/* Barrier synchronization primitive
+ * -- This call will block until all the guest cores are waiting at a common synchronization point
+ * in a yield loop. The core will block at the sync point until the barrier is lowered.
+ *
+ * ARGUMENTS:
+ * vm_info -- The VM for which the barrier is being activated
+ * local_core -- The core whose thread this function is being called from, or NULL
+ * if the calling thread is not associated with a VM's core context
+ */
+
+int v3_raise_barrier(struct v3_vm_info * vm_info, struct guest_info * local_core) {
+ int ret = 0;
+
+
+ if ((vm_info->run_state != VM_RUNNING) ||
+ (vm_info->run_state != VM_SIMULATING)) {
+ return 0;
+ }
+
+ ret = v3_raise_barrier_nowait(vm_info, local_core);
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ return v3_wait_for_barrier(vm_info, local_core);
+}
+
+
+
/* Lowers a barrier that has already been raised
* guest cores will automatically resume execution
* once this has been called
int v3_lower_barrier(struct v3_vm_info * vm_info) {
struct v3_barrier * barrier = &(vm_info->barrier);
+
+ if ((vm_info->run_state != VM_RUNNING) ||
+ (vm_info->run_state != VM_SIMULATING)) {
+ return 0;
+ }
+
// Clear the active flag, so cores won't wait
barrier->active = 0;
return 0;
}
+ V3_Print("Core %d waiting at barrier\n", core->vcpu_id);
+
/* Barrier has been activated.
* Wait here until it's lowered
*/
// set cpu bit in barrier bitmap
v3_bitmap_set(&(barrier->cpu_map), core->vcpu_id);
+ V3_Print("Core %d bit set as waiting\n", core->vcpu_id);
// wait for cpu bit to clear
- while (v3_bitmap_check(&(barrier->cpu_map), core->vcpu_id) == 1) {
- v3_yield(core);
+ while (v3_bitmap_check(&(barrier->cpu_map), core->vcpu_id)) {
+ v3_yield(core,-1);
}
return 0;