/*static char *SCCSID = "@(#)flw.c      6.9 92/01/31";*/
#define  INCL_DOSINFOSEG
#include <os2.h>
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "storage.h"
#include "tables.h"
#include "pb_ifs.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "pbmacros.h"
#include "strat2.h"
#include "asyncio.h"
#include "log.h"

#include "pr_CACHE.h"
#include "pr_debug.h"
#include "pr_LAZY.h"
#include "pr_misc.h"
#include "mmph.h"

/*
 ***    FLW - Flush Lazy Writes
 *
 *      FLW is called to force lazy write operations to the disk.
 *      If the lazy write daemon is present, we pretend that we've gone
 *      idle and yield to him to let him start cleaning things up.
 *
 *      We also walk the cache flushing things too.
 *
 *      Otherwise, we manually do it ourselves.
 *
 *      BUGBUG - right now, we use synchronous write and do them one
 *      at a time.  When we have a better driver, we want to post the
 *      requests in parallel, block, and return when the first one
 *      has been written.  We should have an async notification mechanism
 *      so that we can tell when the first and the last have been written,
 *      keep a flag that says that we're purging the lazys so that we
 *      don't loop too much.
 *
 *      ENTRY   none
 *
 *      EXIT    Yields CPU
 *
 *      PSEUDOCODE
 *              if (Daemon present)
 *                  Wake up/Yield to daemon
 *              for (all buffers in cache)
 *                  if (buffer not locked and buffer on diry chain) {
 *                      remove from dirty chain
 *                      decrement dirty chain count
 *                      if (buffer is dirty)
 *                          BufWrit (buffer)
 *                      }
 *
 *      HISTORY
 *          31-Dec-93 by D.Azzarito   @76903
 *              - Add LOG hooks for start/stop of lazy writer
 *          08-Nov-89 by JR (John Rogers, JohnRo@Microsoft)
 *              - Initial PIC version of scatter/gather support.
 *          28-Sep-1988 09:35:54 by Bill McJohn [t-billm]
 *                              xlated from 9/27/88 assembly code
 */

void
FLW (PFRAME pfrm)
{
    USHORT i;
    USHORT j = 0;
    PVOLTAB pvol = pfrm->pvol;

    MMPHPreFLW(); /* performance hook (330B) */

#ifdef  BUFZAP
    DoZap();
#endif

#ifndef MINIFSD

    if (fLWDaemon) {

          /*  The Lazy Write Daemon is present; force it to
           *  wake up and help us out.
           */
      LazyBlock();                    /* @76903*/
      LWForceWakeUp(pfrm);
      LazyWakeup();                  /* @76903*/

    } else {

#endif

    /*  No Lazy Write Daemon; do the work under the current
     *  thread. Step through the array of buffer headers
     *  seeking a dirty, writable buffer.
     */
    LazyActive();                    /* @76903*/

    for (i = 0; i < cBufs; i++) {

        /*      If the buffer is not locked and not held, and if
         *      it's dirty chain forward pointer is not null,
         *      take it off the dirty chain, decrement the count
         *      of dirty buffers, and write the buffer out if it's
         *      dirty.
         */
        if (((abufCache + i)->cusHolds == 0) &&
            (!((abufCache + i)->fFlag & BFL_LWLOCK)) &&
            ((abufCache + i)->cLocked == 0) &&
            ((abufCache + i)->dcbpDirt.pbufFwd != NULL)) {

             BufWrit(&abufCache[i],pfrm);

             if (++j >= 8)
               break;
        }
    }
#ifndef MINIFSD
    LazyInactive();                  /* @76903*/
    }
#endif

    pfrm->pvol = pvol;

    MMPHPostFLW(); /* performance hook (338B) */
}
