/** * proposer_sync - Send a sync command to all acceptors. * * For a sync to succeed, all acceptors need to tell us the instance number * of their last contiguous learn. We take the minimum of these values * and then command everyone to truncate everything before this minimum. */ int proposer_sync() { int r; struct paxos_header hdr; struct yakyak yy; // If we haven't finished preparing as the proposer, don't sync. if (pax->prep != NULL) { return 1; } // If not everyone is live, we should delay syncing. if (pax->live_count != LIST_COUNT(&pax->alist)) { return 1; } // If our local last contiguous learn is the same as the previous sync // point, we don't need to sync. if (pax->ihole - 1 == pax->sync_prev) { return 0; } // If we're already syncing, increment the skip counter. if (pax->sync != NULL) { // Resync if we've waited too long for the sync to finish. if (++pax->sync->ps_skips < SYNC_SKIP_THRESH) { return 1; } else { g_free(pax->sync); } } // Create a new sync. pax->sync = g_malloc0(sizeof(*(pax->sync))); pax->sync->ps_total = LIST_COUNT(&pax->alist); pax->sync->ps_acks = 1; // Including ourselves. pax->sync->ps_skips = 0; pax->sync->ps_last = 0; // Initialize a header. header_init(&hdr, OP_SYNC, ++pax->sync_id); // Pack and broadcast the sync. yakyak_init(&yy, 1); paxos_header_pack(&yy, &hdr); r = paxos_broadcast(&yy); yakyak_destroy(&yy); return r; }
/******************************************************************************* * apmmgr_event_trigger * * This is the routine which is made available externally to the memory * partitioning module and performs initial event processing */ void apmmgr_event_trigger(apmmgr_attr_t *mpart, mempart_evttype_t evtype, ...) { part_evtlist_t *evt_list; va_list ap; va_start(ap, evtype); // kprintf("%s: mp = %p, evt = %d\n", __func__, mpart, evtype); /* * it is possible that there is no apmmgr_attr_t yet even though there * is an mempart_t (ie. mempart_t.resmgr_attr_p == NULL) */ if (mpart == NULL) return; switch (evtype) { case mempart_evttype_t_DELTA_INCR: case mempart_evttype_t_DELTA_DECR: { /* * additional arguments: * arg1 - current partition size * arg2 - previous partition size (before the increment/decrement */ memsize_t cur_size = va_arg(ap, memsize_t); memsize_t prev_size = va_arg(ap, memsize_t); /* * Since multiple events may be triggered from the DELTA_INCR/DECR, * the check for registered events will be done in _apmmgr_event_trigger() */ _apmmgr_event_trigger(mpart, evtype, cur_size, prev_size); if (cur_size > prev_size) { _apmmgr_event_trigger(mpart, mempart_evttype_t_THRESHOLD_CROSS_OVER, cur_size, prev_size); } else if (cur_size < prev_size) { _apmmgr_event_trigger(mpart, mempart_evttype_t_THRESHOLD_CROSS_UNDER, cur_size, prev_size); } #ifndef NDEBUG else crash(); #endif /* NDEBUG */ break; } case mempart_evttype_t_PROC_ASSOCIATE: case mempart_evttype_t_PROC_DISASSOCIATE: { /* check to see if there are any events of this type registered */ evt_list = &mpart->event_list[MEMPART_EVTYPE_IDX(evtype)]; if (LIST_COUNT(evt_list->active.list) > 0) { /* * addition arguments: * arg1 - pid_t of the associated/disassociated process */ pid_t pid = va_arg(ap, pid_t); #ifdef DISPLAY_EVENT_MSG kprintf("PROC_%sASSOCIATE: pid %d %s associated with mp %p (%s)\n", (evtype == mempart_evttype_t_PROC_DISASSOCIATE) ? "DIS" : "", pid, (evtype == mempart_evttype_t_PROC_DISASSOCIATE) ? "no longer" : "now", mpart, mpart->name); #endif /* DISPLAY_EVENT_MSG */ /* * for disassociation events, we optionally check whether a * specific process id of interest has been provided */ if (evtype == mempart_evttype_t_PROC_DISASSOCIATE) { SEND_MP_EVENT(evt_list, (void *)&pid, pid_match); } else { SEND_MP_EVENT(evt_list, (void *)&pid, NULL); } } break; } case mempart_evttype_t_CONFIG_CHG_ATTR_MIN: { /* check to see if there are any events of this type registered */ evt_list = &mpart->event_list[MEMPART_EVTYPE_IDX(evtype)]; if (LIST_COUNT(evt_list->active.list) > 0) { /* * addition arguments: * arg1 - previous configuration (mempart_cfg_t *) * arg2 - current configuration (mempart_cfg_t *) * * From these args the 'cfg_chg.attr.min' will be built an sent * to any registered processes */ mempart_cfg_t *prev = va_arg(ap, mempart_cfg_t *); mempart_cfg_t *cur = va_arg(ap, mempart_cfg_t *); if (cur->attr.size.min != prev->attr.size.min) { #ifdef DISPLAY_EVENT_MSG kprintf("CONFIG_CHG_ATTR_MIN: mp %p (%s) from %P to %P\n", mpart, mpart->name, (paddr_t)prev->attr.size.min, (paddr_t)cur->attr.size.min); #endif /* DISPLAY_EVENT_MSG */ SEND_MP_EVENT(evt_list, (void *)&cur->attr.size.min, NULL); } } break; } case mempart_evttype_t_CONFIG_CHG_ATTR_MAX: { /* check to see if there are any events of this type registered */ evt_list = &mpart->event_list[MEMPART_EVTYPE_IDX(evtype)]; if (LIST_COUNT(evt_list->active.list) > 0) { /* * addition arguments: * arg1 - previous configuration (mempart_cfg_t *) * arg2 - current configuration (mempart_cfg_t *) * * From these args the 'cfg_chg.attr.max' will be built an sent * to any registered processes */ mempart_cfg_t *prev = va_arg(ap, mempart_cfg_t *); mempart_cfg_t *cur = va_arg(ap, mempart_cfg_t *); if (cur->attr.size.max != prev->attr.size.max) { #ifdef DISPLAY_EVENT_MSG kprintf("CONFIG_CHG_ATTR_MAX: mp %p (%s) from %P to %P\n", mpart, mpart->name, (paddr_t)prev->attr.size.max, (paddr_t)cur->attr.size.max); #endif /* DISPLAY_EVENT_MSG */ SEND_MP_EVENT(evt_list, (void *)&cur->attr.size.max, NULL); } } break; }
/* * __apmmgr_event_trigger2 * * This routine will handle all of the possible memory class DELTA and * THRESHOLD_CROSS events. It is only called from _apmmgr_event_trigger2() */ static INLINE void __apmmgr_event_trigger2(apmmgr_attr_t *mpart, memclass_evttype_t evtype, memsize_t cur_size, memsize_t prev_size) { part_evtlist_t *evt_list; /* check to see if there are any events of this type registered */ evt_list = &mpart->event_list[MEMCLASS_EVTYPE_IDX(evtype)]; if (LIST_COUNT(evt_list->active.list) == 0) return; switch (evtype) { /* handle all the deltas */ case memclass_evttype_t_DELTA_TF_INCR: case memclass_evttype_t_DELTA_TF_DECR: case memclass_evttype_t_DELTA_RF_INCR: case memclass_evttype_t_DELTA_RF_DECR: case memclass_evttype_t_DELTA_UF_INCR: case memclass_evttype_t_DELTA_UF_DECR: case memclass_evttype_t_DELTA_TU_INCR: case memclass_evttype_t_DELTA_TU_DECR: case memclass_evttype_t_DELTA_RU_INCR: case memclass_evttype_t_DELTA_RU_DECR: case memclass_evttype_t_DELTA_UU_INCR: case memclass_evttype_t_DELTA_UU_DECR: { #ifdef DISPLAY_EVENT_MSG kprintf("%s: mp %p (%s) from %P to %P\n", mclass_evt_string(evtype), mpart, mpart->name, (paddr_t)prev_size, (paddr_t)cur_size); #endif /* DISPLAY_EVENT_MSG */ if (cur_size > prev_size) { SEND_MC_DELTA_INCR_EVENTS(evt_list, cur_size, prev_size); } else if (cur_size < prev_size) { SEND_MC_DELTA_DECR_EVENTS(evt_list, cur_size, prev_size); } #ifndef NDEBUG else crash(); #endif /* NDEBUG */ break; } case memclass_evttype_t_THRESHOLD_CROSS_TF_OVER: case memclass_evttype_t_THRESHOLD_CROSS_TF_UNDER: case memclass_evttype_t_THRESHOLD_CROSS_TU_OVER: case memclass_evttype_t_THRESHOLD_CROSS_TU_UNDER: case memclass_evttype_t_THRESHOLD_CROSS_RF_OVER: case memclass_evttype_t_THRESHOLD_CROSS_RF_UNDER: case memclass_evttype_t_THRESHOLD_CROSS_UF_OVER: case memclass_evttype_t_THRESHOLD_CROSS_UF_UNDER: case memclass_evttype_t_THRESHOLD_CROSS_RU_OVER: case memclass_evttype_t_THRESHOLD_CROSS_RU_UNDER: case memclass_evttype_t_THRESHOLD_CROSS_UU_OVER: case memclass_evttype_t_THRESHOLD_CROSS_UU_UNDER: { #ifdef DISPLAY_EVENT_MSG kprintf("%s: mp %p (%s) from %P to %P\n", mclass_evt_string(evtype), mpart, mpart->name, (paddr_t)prev_size, (paddr_t)cur_size); #endif /* DISPLAY_EVENT_MSG */ if (cur_size > prev_size) { SEND_MC_THRESHOLD_X_OVER_EVENTS(evt_list, cur_size, prev_size); } else if (cur_size < prev_size) { SEND_MC_THRESHOLD_X_UNDER_EVENTS(evt_list, cur_size, prev_size); } #ifndef NDEBUG else crash(); #endif /* NDEBUG */ break; } default: #ifdef DISPLAY_EVENT_MSG kprintf("Unknown event: %d\n", evtype); #endif /* DISPLAY_EVENT_MSG */ break; } }
/* * _apmmgr_event_trigger * * This is the routine which is made available externally to the memory * partitioning module and performs initial event processing */ static void _apmmgr_event_trigger(apmmgr_attr_t *mpart, memclass_evttype_t evtype, memsize_t cur_size, memsize_t prev_size) { part_evtlist_t *evt_list; /* * it is possible that there is no apmmgr_attr_t yet even though there * is an mempart_t (ie. mempart_t.resmgr_attr_p == NULL) */ if (mpart == NULL) return; /* check to see if there are any events of this type registered */ evt_list = &mpart->event_list[MEMPART_EVTYPE_IDX(evtype)]; if (LIST_COUNT(evt_list->active.list) == 0) return; switch (evtype) { case mempart_evttype_t_THRESHOLD_CROSS_OVER: case mempart_evttype_t_THRESHOLD_CROSS_UNDER: { #ifdef DISPLAY_EVENT_MSG kprintf("THRESHOLD_CROSS %s: mp %p (%s) from %P to %P\n", (cur_size > prev_size) ? "over" : ((cur_size < prev_size) ? "under" : "?"), mpart, mpart->name, (paddr_t)prev_size, (paddr_t)cur_size); #endif /* DISPLAY_EVENT_MSG */ if (cur_size > prev_size) { SEND_MP_THRESHOLD_X_OVER_EVENTS(evt_list, cur_size, prev_size); } else if (cur_size < prev_size) { SEND_MP_THRESHOLD_X_UNDER_EVENTS(evt_list, cur_size, prev_size); } #ifndef NDEBUG else crash(); #endif /* NDEBUG */ break; } case mempart_evttype_t_DELTA_INCR: case mempart_evttype_t_DELTA_DECR: { #ifdef DISPLAY_EVENT_MSG kprintf("DELTA %s: mp %p (%s) from %P to %P\n", (cur_size > prev_size) ? "incr" : ((cur_size < prev_size) ? "decr" : "?"), mpart, mpart->name, (paddr_t)prev_size, (paddr_t)cur_size); #endif /* DISPLAY_EVENT_MSG */ if (cur_size > prev_size) { SEND_MP_DELTA_INCR_EVENTS(evt_list, cur_size, prev_size); } else if (cur_size < prev_size) { SEND_MP_DELTA_DECR_EVENTS(evt_list, cur_size, prev_size); } #ifndef NDEBUG else crash(); #endif /* NDEBUG */ break; } default: #ifdef DISPLAY_EVENT_MSG kprintf("Unknown event: %d\n", evtype); #endif /* DISPLAY_EVENT_MSG */ break; } }