From 951957e0ed5b7c96df9f4fbacfe1933246848d1c Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 29 Dec 2010 17:04:41 +0000 Subject: [PATCH] movpos: wip multiple movfeatkinds: new indep/meth protocol, is good. wip --- hostside/movpos.c | 271 ++++++++++++++++++++++++++++------------------ 1 file changed, 165 insertions(+), 106 deletions(-) diff --git a/hostside/movpos.c b/hostside/movpos.c index d669286..fc09eb3 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -29,7 +29,7 @@ typedef struct Method Method; * at points when control flow passes between kind and indep: * U Unallocated no memory allocated (Change does not exist) * P Prepared memory allocation done, basics filled in - * Q Queued reservation or confirmation successful + * I Installed reservation or confirmation successful * D Done motion is complete and callback is being entered * G Garbage motion is complete and callback is being exited * @@ -43,27 +43,31 @@ typedef struct Method Method; typedef struct Change Change; struct Change { /* valid in: filled in by and when: */ - Method *meth; /* PQ indep after prepare() */ - MovPosChange *indep; /* PQ indep after prepare() */ + Method *meth; /* PIDG indep after prepare() */ + MovPosChange *indep; /* PID indep after prepare() */ /* kind-specific data follows */ /* varies kind-specific code, varies */ } Change; struct Method { const char *pname; - MovFeatKind kind; + unsigned needcheck, needexec; /* used by indep to track T/Y/E */ + ErrorCode (*prepare)(Method *m, /* TYE->T */ Segment *move, int n_motions, const Motion *motions, int ms, int confirming, Change *chg_r, /* 0->P; err: 0->0; may be 0 */ int *cost_r /* may be 0 */); - ErrorCode (*consider)(Method *m, /* TYE->T */ - Change *remove, /* Q->P; err: Q->Q */ - Change *install); /* P->Q; err: P->P */ - /* error: ET->T, no change to Changes */ void (*dispose)(Method *m, /* TY->TY */ Change*); /* P->U */ + ErrorCode (*install)(Method *m, /* TYE->T; err: TYE->TYY */ + Change *inst); /* P->I; err: P->P */ + /* error: ET->T, no change to Changes */ + void (*remove)(Method *m, /* TYE->TYY */ + Change *remove); /* I->P */ + /* error: ET->T, no change to Changes */ + ErrorCode (*check)(Method *m); /* TYE->Y; err: TYE->TYE */ void (*execute)(Method *m); /* EY->E */ void (*all_abandon)(Method *m); /* I */ @@ -346,21 +350,24 @@ static ErrorCode fsq_prepare(Method *mm, Segment *move, return 0; } -static ErrorCode fsq_consider(Method *mm, Change *remove, Change *install) { +static void fsq_dispose(Method *mm, Change *chg) { FsqMethod *m= (void*)mm; - FsqReq *remv= (FsqReq*)remove; - FsqReq *inst= (FsqReq*)install; + FsqReq *r= (FsqReq*)chg; + free(r); +} - DPRINTF1(movpos,fsq, "%s consider ", m->m.pname); +static void fsq_remove(Method *mm, Change *instchg) { + FsqMethod *m= (void*)mm; + FsqReq *remv= (FsqReq*)remvchg; fsq_dequeue(m, remv); - ErrorCode ec= fsq_enqueue(m, inst); - if (ec) { - ErrorCode ec2= fsq_enqueue(m, remv); - assert(!ec2); - } - DPRINTF1(movpos,fsq, " %s\n", ec2str(ec)); - return ec; +} + +static ErrorCode fsq_install(Method *mm, Change *instchg) { + FsqMethod *m= (void*)mm; + FsqReq *inst= (FsqReq*)instchg; + + return fsq_enqueue(m, inst); } static ErrorCode fsq_check(Method *mm) { @@ -376,12 +383,6 @@ static void fsq_execute(Method *mm) { fsq_check_action(m); } -static void fsq_dispose(Method *mm, Change *chg) { - FsqMethod *m= (void*)mm; - FsqReq *r= (FsqReq*)chg; - free(r); -} - /*---------- something to do ? ----------*/ static void fsq_check_action(FsqMethod *m) { @@ -587,32 +588,78 @@ static FsqMethod waggle= { /*========== dummy `nomove' kind ==========*/ -static ErrorCode nomove_prepare(Method *m, Segment *move, +typedef struct NomoveChange { + Change h; + DLIST_NODE inqueue; + int n_motions; + Motion motions[]; +}; + +typedef struct { + Method m; + unsigned eventqueued:1; + NomoveChange *queuehead; +} NomoveMethod; + +static ErrorCode nomove_prepare(Method *meth_in, Segment *move, int n_motions, const Motion *motions, int ms, int confirming, Change *chg_r, int *cost_r) { if (chg_r) { - *chg= mmalloc(sizeof(Change)); - fixme + NomoveChange *chg; + chg= mmalloc(sizeof(*chg) + sizeof(Motion)*n_motions); + chg->n_motions= n_motions; + memcpy(chg->motions, motions, sizeof(Motion)*n_motions); } if (cost_r) { *cost_r= 0; } return 0; } +static void nomove_dispose(Method *mm, Change *remvchg) { + NomoveChange *remv= (void*)remvchg; + free(remv); +} -static ErrorCode nomove_consider(Method *m, Change *remove, Change *install) - { return 0; } +static ErrorCode nomove_install(Method *mm, Change *instchg) { + NomoveMethod *meth= (void*)mm; + NomoveChange *inst= (void*)instchg; + DLIST1_PREPEND(meth->queuehead, inst, inqueue); + return 0; +} +static void nomove_remove(Method *mm, Change *remvchg) { + NomoveMethod *meth= (void*)mm; + NomoveChange *remv= (void*)remvchg; + DLIST1_REMOVE(meth->queuehead, remv, inqueue); +} -static void nomove_dispose(Method *m, Change *chg) { } -static ErrorCode nomove_check(Method *m) { return 0; } -static ErrorCode nomove_execute(Method *m) { - fixme +static ErrorCode nomove_check(Method *mm) { return 0; } + +static void (*nomove_execute_now)(oop_source *source, struct timeval tv, + void *meth_v) { + NomoveMethod *meth= meth_v; + meth->eventqueued= 0; + NomoveChange *done; + while ((done= meth->queuehead)) { + for (i=0; in_motions; i++) + method_update_feature(&meth->m, done->indep, &done->motions[i]); + method_change_done(&meth->m, &done->h); + DLIST1_REMOVE(meth->queuehead, done, inqueue); + nomove_dispose(&meth->m, &done->h); + } } - +static void nomove_execute(Method *mm) { + NomoveMethod *meth= (void*)mm; + if (!meth->eventqueued) { + meth->eventqueued= 1; + events->on_time(events, OOP_TIME_NOW, nomove_execute_now, meth); + } +} + static Method nomove_method= { "nomove", mfk_none, - nomove_prepare, nomove_consider, nomove_dispose, + nomove_prepare, nomove_dispose, + nomove_install, nomove_remove, nomove_check, nomove_execute, ignore_all_abandon }; @@ -621,22 +668,21 @@ static Method nomove_method= { struct MovPosChange { Segment *move; MovPosComb actual, target; + unsigned installed:1; int n_changes; Change *changes[]; }; - static Method *methods[]= { - &nomove_method, - (Method*)&points_method, - (Method*)&waggle, - 0 + [mfk_none] = (Method*)&nomove_method, + [mfk_point] = (Method*)&points_method, + [mfk_relay] = (Method*)&waggle, }; /*---------- entrypoints from methods ----------*/ static void method_update_feature(Method *m, MovPosChange *indep, - const Motion *mo) { + const Motion *mo) { /* Called from methods' execution logic when an individual feature * has been moved. This is used by the method-independent code to * compute the correct delta set of movements from the current @@ -684,13 +730,21 @@ static void method_change_done(Method *m, Change *chg) { /*---------- internal core machinery ----------*/ +static Method *feature_method(MovFeatInfo *feati) { + assert(feati->kind >= 0); + assert(feati->kind < ARRAY_SIZE(methods)); + Method *meth= methods[feati->kind]; + assert(meth); + return meth; +} + static int change_needed(const MovFeatInfo *feati, MovPosComb startpoint, MovPosComb target) { int r; r= !SOMEP(startpoint) || (target - startpoint) / feati->weight % feati->posns; DPRINTF(movpos,changeneeded, "%s:%s(%d*%d) %d..%d => %d\n", - methods[feati->kind]->pname, feati->pname, + feature_method(feati)->pname, feati->pname, feati->posns, feati->weight, startpoint, target, r); return r; @@ -731,7 +785,7 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target, feat++, feati++) { if (!change_needed(feati,startpoint,target)) continue; MovPosComb posn= target / feati->weight % feati->posns; - Method *meth= methods[kind]; + Method *meth= feature_method(feati); int methi; for (methi=0; methichanges, 0, sizeof(Change*) * n_meths); indep->move= move; - indep->start= startpoint; + indep->actual= startpoint; indep->target= target; + indep->considering= 0; } DPRINTF(movpos,eval, "\n"); @@ -767,6 +822,8 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target, for (int changei=0; changeineedcheck= 1; + meth->needexec= 1; ec= meth->prepare(meth,move, n_motions[changei],motions[changei], ms, confirming, @@ -794,66 +851,58 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target, return ec; } +static void indep_remove(MovPosChange *remv) { + if (!remv) return; + + for (i=0; in_changes; i++) { + Change *chg= inst->changes[i]; + if (!chg->installed) continue; + Method *meth= chg->meth; + meth->needexec= 1; + meth->remove(meth, chg); + } +} + static ErrorCode -indep_consider(MovPosChange *remv, MovPosChange *inst) { - /* does consider and check; on failure, it does consider on remv - * and check (which is guaranteed to always succeed) */ - assert(inst->n_changes <= 32); - assert(remv->n_changes <= 32); - uint32_t inst_done, remv_done; - int inst2remv[inst->n_changes]; /* valid only if inst_done; -ve => none */ - - int ii, jj; +indep_install(MovPosChange *inst, int needcheck) { + /* if this fails, inst may be left partially installed */ + if (!inst) return 0; - for (ii=0; iin_changes; ii++) { - Method *meth= inst->changes[ii].meth; - for (jj=remv->n_changes-1; jj>=0; jj++) - if (remv->changes[jj].meth == meth) break; - ec= meth->consider(meth, - jj>=0 ? remv->changes[jj] : 0, - inst->changes[ii]); + for (i=0; in_changes; i++) { + Change *chg= inst->changes[n_installed]; + assert(!chg->installed); + Method *meth= chg->meth; + meth->needexec= 1; + ec= meth->install(meth, chg); if (ec) goto x; + chg->installed= 1; - inst_done |= (1UL << ii); - inst2remv[ii]= jj; - if (jj>=0) remv_done |= (1UL << jj); - - ec= meth->check(meth); - if (ec) goto x; - } - for (jj=0; jjn_changes; jj++) { - if (remv_done & (1UL << jj)) continue; - ec= meth->consider(meth, remv->changes[jj], 0); - assert(!ec); - ec= meth->check(meth); - assert(!ec); - /* remv_done |= (1UL << jj); - not needed because we never roll back from here */ + if (needcheck) { + meth->needcheck= 1; + ec= meth->check(meth); + if (ec) goto x; + meth->needcheck= 0; + } } - return 0; + inst->installed= 1; x: - for (ii=0; iin_changes; ii++) { - if (!(inst_done & (1UL << ii))) continue; - Method *meth= inst->changes[ii].meth; - jj= inst2remv[ii]; - ec= meth->consider(meth, - inst->changes[ii], - jj>=0 ? remv->changes[jj] : 0); - assert(!ec); - ec= meth->check(meth); - assert(!ec); - } - /* we do not need to unwind methods for which we are only removing - * since we never roll back after starting those */ return ec; } -static void indep_execute(void) { +static void indep_check_execute(void) { for (Method **methwalk= methods; (meth= *methwalk); methwalk++) { - meth->execute(meth); + if (meth->needcheck) { + ec= meth->check(meth); + assert(!ec); + meth->needcheck= 0; + } + if (meth->needexec) { + meth->needexec= 0; + meth->execute(meth); + } } } @@ -882,19 +931,20 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, maxdelay_ms, movpos_pname(move,startpoint)); ec= indep_prepare(move,target, startpoint, - ms,0, - &indep, 0); + ms,0, + &indep, 0); if (ec) return ec; - ec= indep_consider(0, indep); + ec= indep_install(indep, 1); if (ec) goto x; - indep_execute(); + indep_check_execute(); return 0; x: + indep_remove(indep); indep_dispose(indep); - indep_execute(); + indep_check_execute(); return ec; } @@ -951,23 +1001,33 @@ ErrorCode movpos_change(Segment *move, MovPosComb target, chg->meth->pname, chg->move->i->pname, movpos_pname(chg->move, chg->intent)); - MovPosChange *indep= 0; + MovPosChange *inst= 0; ec= indep_prepare(move,target, actual, maxdelay_ms,1, - &indep, 0); + &inst, 0); if (ec) goto x; - ec= indep_consider(resv, indep); + indep_remove(resv); + indep_remove(move->motion);; + + ec= indep_install(inst, 1); if (ec) goto x; indep_dispose(resv); - indep_execute(); + indep_dispose(move->motion); + + move->motion= inst; + + indep_check_execute(); return 0; x: - indep_dispose(indep); - indep_execute(); + indep_remove(inst); + indep_dispose(inst); + ec= indep_install(move->motion, 0); assert(!ec); + ec= indep_install(resv, 0); assert(!ec); + indep_check_execute(); return ec; } @@ -976,10 +1036,9 @@ void movpos_unreserve(MovPosChange *resv) { DPRINTF(movpos,unreserve, "%s:%s/%s\n", res->meth->pname, res->move->i->pname, movpos_pname(res->move, res->intent)); - ErrorCode ec= indep_consider(resv, 0); - assert(!ec); + indep_remove(resv); indep_dispose(resv); - indep_execute(); + indep_check_execute(); } MovPosComb movpos_change_intent(MovPosChange *indep) { -- 2.30.2