home *** CD-ROM | disk | FTP | other *** search
- /* cache.c */
-
- /*#define NOCACHE*/
- #define NOWRITEBEHIND
-
- #include "chunks.h"
- #include "debug.h"
- #include "module.h"
- #include "swis.h"
- #include <stdlib.h>
- #include <string.h>
-
- static int xFiles__timer;
-
- #define xFiles_CACHECHUNKSIZE 1024
- #define xFiles_OK2CACHE 4096
-
- #define roundDown(x) ((x) & ~(xFiles_CACHECHUNKSIZE-1))
- #define roundUp(x) roundDown((x) + xFiles_CACHECHUNKSIZE - 1)
-
- typedef struct
- {
- int prev, next; /* Index into the array of cache chunks or -1 for NULL */
- unsigned owner; /* (unsigned) pInfo for this chunk or 0 if unused */
- unsigned offset; /* Offset in file where it started */
- char *buffer;
- BOOL dirty;
-
- } xFiles_cacheItem;
-
- static xFiles_cacheItem *cache;
- static char *buffer;
- static int cacheHead, cacheTail;
- static int cacheSize, cacheUsed; /* elements that is */
-
- void *xFiles_windowBuffer; /* shared by all and sundry */
- int xFiles_windowBufferSize;
- static BOOL xFiles__bufferClaimed;
-
- #define _max(x, y) ((x) > (y) ? (x) : (y))
- #define _min(x, y) ((x) < (y) ? (x) : (y))
-
- static void xFiles__disposeCache(void)
- {
- if (cache)
- {
- free(cache);
- cache = NULL;
- }
-
- if (buffer)
- {
- free(buffer);
- buffer = NULL;
- }
- }
-
- void xFiles_Tidy(void)
- {
- if (xFiles_windowBuffer)
- {
- free(xFiles_windowBuffer);
- xFiles_windowBuffer = NULL;
- }
-
- xFiles__disposeCache();
- }
-
- _kernel_oserror *xFiles_releaseBuffer(void)
- {
- xFiles__bufferClaimed = FALSE;
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_claimBuffer(int notBiggerThan)
- {
- (void) notBiggerThan;
-
- if (xFiles__bufferClaimed)
- return &xFiles_BufferInUse;
-
- xFiles__bufferClaimed = TRUE;
-
- if (xFiles_windowBuffer)
- return NULL;
-
- if (xFiles_windowBuffer = malloc(xFiles_WINDOWSIZE), !xFiles_windowBuffer)
- return &xFiles_NoMemory;
-
- xFiles_windowBufferSize = xFiles_WINDOWSIZE;
-
- return NULL;
- }
-
- static void xFiles_RemoveCacheItem(int item)
- {
- if (cache[item].prev != -1)
- cache[cache[item].prev].next = cache[item].next;
- else
- cacheHead = cache[item].next;
-
- if (cache[item].next != -1)
- cache[cache[item].next].prev = cache[item].prev;
- else
- cacheTail = cache[item].prev;
-
- cache[item].next =
- cache[item].prev = -1;
- }
-
- static void xFiles_CacheAddAtHead(int item)
- {
- if (cacheHead != -1)
- cache[cacheHead].prev = item;
- else
- cacheTail = item;
-
- cache[item].prev = -1;
- cache[item].next = cacheHead;
- cacheHead = item;
- }
-
- static void xFiles_CacheAddAtTail(int item)
- {
- if (cacheTail != -1)
- cache[cacheTail].next = item;
- else
- cacheHead = item;
-
- cache[item].next = -1;
- cache[item].prev = cacheTail;
- cacheTail = item;
- }
-
- _kernel_oserror *xFiles_getLength(xFiles_info *pInfo, unsigned *pLength)
- {
- _kernel_swi_regs regs;
- _kernel_oserror *err;
-
- if (pInfo->fileSize == (unsigned) -1)
- {
- regs.r[0] = 2;
- regs.r[1] = pInfo->fileHandle;
-
- if (err = _kernel_swi(OS_Args, ®s, ®s), err)
- return err;
-
- pInfo->fileSize = (unsigned) regs.r[2];
- }
-
- if (pLength) *pLength = pInfo->fileSize;
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_setLength(xFiles_info *pInfo, unsigned Length)
- {
- _kernel_swi_regs regs;
- _kernel_oserror *err;
- int i;
- unsigned owner = (unsigned) pInfo;
- unsigned oldLength;
-
- /*TRACE("xFiles_setLength(%p, %08x)\n", pInfo, Length);*/
-
- if (err = xFiles_getLength(pInfo, &oldLength), err)
- return err;
-
- /* If the file is shrinking we need to discard any items which are cached
- * for the bit of file which no longer exists, otherwise when the file
- * grows again these bits will be mistaken for valid bits of file.
- */
-
- if (Length < oldLength)
- {
- for (i = 0; i < cacheUsed; i++)
- {
- if (cache[i].owner == owner && cache[i].offset >= Length)
- {
- cache[i].offset = 0xFFFFFFFF;
- cache[i].dirty = FALSE;
- xFiles_RemoveCacheItem(i);
- xFiles_CacheAddAtTail(i);
- }
-
- if (cache[i].offset == 0xFFFFFFFF)
- cache[i].owner = i > 0 ? cache[i-1].owner + 1 : 0;
- }
- }
-
- regs.r[0] = 3;
- regs.r[1] = pInfo->fileHandle;
- regs.r[2] = (int) Length;
-
- if (err = _kernel_swi(OS_Args, ®s, ®s), err)
- return err;
-
- pInfo->fileSize = Length;
- return NULL;
- }
-
- /* Read a glob of the file into the specified buffer.
- * This is about as primitive as it gets.
- */
-
- static _kernel_oserror *xFiles_rawRead(xFiles_info *pInfo, void *pBuffer, unsigned pos, unsigned size)
- {
- _kernel_swi_regs regs;
- _kernel_oserror *err;
-
- /*TRACE(" xFiles_rawRead(%p, %p, %08x, %08x)\n", pInfo, pBuffer, pos, size);*/
-
- regs.r[0] = 3; /* read bytes given pointer */
- regs.r[1] = pInfo->fileHandle;
- regs.r[2] = (int) pBuffer;
- regs.r[3] = size;
- regs.r[4] = pos;
-
- if (err = _kernel_swi(OS_GBPB, ®s, ®s), err)
- return err;
-
- if (regs.r[3] > 0)
- {
- TRACE("*** %d bytes not read\n", regs.r[3]);
- }
-
- return NULL;
- }
-
- static _kernel_oserror *xFiles_rawWrite(xFiles_info *pInfo, void *pBuffer, unsigned pos, unsigned size)
- {
- _kernel_swi_regs regs;
-
- /*TRACE(" xFiles_rawWrite(%p, %p, %08x, %08x)\n", pInfo, pBuffer, pos, size);*/
-
- regs.r[0] = 1; /* write bytes given pointer */
- regs.r[1] = pInfo->fileHandle;
- regs.r[2] = (int) pBuffer;
- regs.r[3] = size;
- regs.r[4] = pos;
-
- return _kernel_swi(OS_GBPB, ®s, ®s);
- }
-
- static void xFiles_EmptyCache()
- {
- int i;
- char *bp;
-
- cacheHead =
- cacheTail = -1;
-
- /* Offsets within the buffer are statically associated with particular
- * index entries, so this relationship is established here.
- */
-
- for (i = 0, bp = buffer; i < cacheSize; i++, bp += xFiles_CACHECHUNKSIZE)
- {
- cache[i].prev =
- cache[i].next = -1;
- cache[i].owner = 0;
- cache[i].offset = 0;
- cache[i].buffer = bp;
- cache[i].dirty = FALSE;
- }
-
- cacheUsed = 0;
- }
-
- static int xFiles_CacheCmp(unsigned owner, unsigned offset, int item)
- {
- return (owner == cache[item].owner) ? (offset - cache[item].offset)
- : (owner - cache[item].owner);
- }
-
- static int xFiles_CacheLookup(xFiles_info *pInfo, unsigned offset)
- {
- unsigned owner = (unsigned) pInfo;
- int lo, hi, mid, cmp;
-
- for (lo = 0, hi = cacheUsed-1; lo <= hi; )
- {
- mid = (lo + hi) / 2;
- cmp = xFiles_CacheCmp(owner, offset, mid);
-
- if (cmp < 0)
- hi = mid - 1;
- else if (cmp > 0)
- lo = mid + 1;
- else
- return mid;
- }
-
- return -1;
- }
-
-
- _kernel_oserror *xFiles_InitCache(unsigned size)
- {
- #ifdef NOCACHE
- (void) size;
- #else
- cacheSize = size / xFiles_CACHECHUNKSIZE;
-
- xFiles__disposeCache();
-
- xFiles__timer = 0;
-
- if (cacheSize == 0)
- {
- cache = NULL;
- return NULL;
- }
-
- if (cache = malloc(sizeof(xFiles_cacheItem) * cacheSize), !cache)
- goto fail;
-
- if (buffer = malloc(xFiles_CACHECHUNKSIZE * cacheSize), !buffer)
- goto fail;
-
- xFiles_EmptyCache();
-
- return NULL;
-
- fail:
- xFiles__disposeCache();
- cacheSize = 0;
- TRACE("Not enough space for cache; running with cache disabled");
- #endif
- return NULL;
- }
-
- _kernel_oserror *xFiles_FlushFileInfo(xFiles_info *pInfo)
- {
- int i;
- unsigned owner = (unsigned) pInfo;
- _kernel_oserror *err;
-
- if (err = xFiles_Flush(), err)
- return err;
-
- for (i = 0; i < cacheUsed; i++)
- {
- if (cache[i].owner == owner)
- {
- cache[i].offset = 0xFFFFFFFF;
- cache[i].dirty = FALSE;
- xFiles_RemoveCacheItem(i);
- xFiles_CacheAddAtTail(i);
- }
-
- if (cache[i].offset == 0xFFFFFFFF)
- cache[i].owner = i > 0 ? cache[i-1].owner + 1 : 0;
- }
-
- return NULL;
- }
-
- static void xFiles_AdjustCache(int item, int by)
- {
- int i;
-
- ASSERT(item != -1);
-
- for (i = 0; i < cacheUsed; i++)
- {
- ASSERT(by > 0 || cache[i].prev != item);
- ASSERT(by > 0 || cache[i].next != item);
-
- if (cache[i].prev >= item)
- cache[i].prev += by;
- if (cache[i].next >= item)
- cache[i].next += by;
- }
-
- ASSERT(by > 0 || cacheHead != item);
- ASSERT(by > 0 || cacheTail != item);
-
- if (cacheHead >= item)
- cacheHead += by;
- if (cacheTail >= item)
- cacheTail += by;
- }
-
- static void xFiles_CacheCheck(void)
- {
- int prev, i, watchDog;
- int broken = 0;
- xFiles_info *pInfo;
-
- if (!cache)
- return;
-
- if (cacheUsed > cacheSize)
- goto trash;
-
- prev = -1;
- i = cacheHead;
- watchDog = cacheUsed+1;
-
- while (watchDog > 0 && i != -1)
- {
- if (cache[i].prev != prev)
- {
- TRACE("Cache back link is %d (should be %d)\n", cache[i].prev, prev);
- broken++;
- }
-
- prev = i;
- i = cache[i].next;
- watchDog--;
- }
-
- if (watchDog == 0)
- {
- TRACE("Loop in cache links\n");
- broken++;
- }
- else if (cacheTail != prev)
- {
- TRACE("cacheTail should is %d (should be %d)\n", cacheTail, prev);
- broken++;
- }
-
- for (i = 0; i < cacheUsed-1; i++)
- {
- int cmp = xFiles_CacheCmp(cache[i].owner, cache[i].offset, i+1);
-
- if (cmp >= 0)
- {
- TRACE("Cache items are not ordered/unique\n");
- broken++;
- break;
- }
-
- pInfo = (xFiles_info *) cache[i].owner;
- if (cache[i].offset != 0xFFFFFFFF && cache[i].offset >= pInfo->fileSize)
- {
- TRACE("Cache item outside file's length (offset = %08x, fileSize = %08x)\n",
- cache[i].offset, pInfo->fileSize);
- broken++;
- break;
- }
- }
-
- if (broken == 0)
- return;
-
- trash:
- TRACE("Cache is broken: discarding it\n");
-
- TRACE("Head: %d, Tail: %d, Size: %d, Used: %d\n", cacheHead, cacheTail, cacheSize, cacheUsed);
- for (i = 0; i < _min(cacheUsed, cacheSize); i++)
- {
- TRACE("%3d: %08x, %08x, %3d, %3d\n",
- i, cache[i].owner, cache[i].offset, cache[i].prev, cache[i].next);
- }
-
- cacheUsed = 0;
- cacheHead = cacheTail = -1;
- }
-
- /* Ensure the chunk with the specified offset is in the cache, returning it's index.
- * If the chunk isn't in the cache it will be loaded from the file replacing the
- * least recently used item in the cache.
- */
-
- static _kernel_oserror *xFiles_CacheEnsure(xFiles_info *pInfo, unsigned offset, int *pItem, BOOL noRead)
- {
- int item;
- unsigned owner = (unsigned) pInfo;
- _kernel_oserror *err;
- xFiles_cacheItem tmp;
-
- ASSERT(offset == roundDown(offset));
- ASSERT(cacheUsed <= cacheSize);
-
- if (item = xFiles_CacheLookup(pInfo, offset), item != -1)
- {
- /*TRACE("%p, %08x -- cache hit\n", pInfo, offset);*/
- xFiles_RemoveCacheItem(item);
- xFiles_CacheAddAtHead(item);
- *pItem = item;
- return NULL;
- }
-
- /*TRACE("%p, %08x -- cache miss\n", pInfo, offset);*/
-
- /* If the cache is full get rid of a chunk. What actually happens is that the chunk to
- * be discarded is moved up to the end of the cache. We can't actually throw it away
- * because each chunk refers to its own bit of buffer and that only gets allocated once.
- */
-
- if (cacheUsed == cacheSize)
- {
- item = cacheTail;
-
- ASSERT(cacheTail != -1);
-
- if (cache[item].dirty)
- {
- if (cache[item].offset != 0xFFFFFFFF)
- {
- /*TRACE("Flush(1) %08x, %08x, %08x\n",
- cache[item].owner, cache[item].buffer, cache[item].offset);*/
-
- if (err = xFiles_rawWrite((xFiles_info *) cache[item].owner,
- cache[item].buffer, cache[item].offset,
- xFiles_CACHECHUNKSIZE), err)
- return err;
- }
-
- cache[item].dirty = FALSE;
- }
-
- tmp = cache[item]; /* save it */
-
- /*TRACE(" discarding item %d (%08x, %08x)\n",
- item, cache[item].owner, cache[item].offset);*/
-
- xFiles_RemoveCacheItem(item); /* remove from the linked list */
- cacheUsed--;
- memmove(&cache[item], &cache[item+1], sizeof(xFiles_cacheItem) * (cacheUsed - item));
- xFiles_AdjustCache(item, -1);
- cache[cacheUsed] = tmp;
- }
-
- for (item = 0; item < cacheUsed && xFiles_CacheCmp(owner, offset, item) > 0; item++)
- ;
-
- /*TRACE(" inserting as item %d\n", item);*/
-
- tmp = cache[cacheUsed]; /* Get the unused one at the end */
- if (item < cacheUsed)
- memmove(&cache[item+1], &cache[item], sizeof(xFiles_cacheItem) * (cacheUsed - item));
- cacheUsed++;
- xFiles_AdjustCache(item, 1);
- cache[item] = tmp;
- xFiles_CacheAddAtHead(item);
- cache[item].owner = owner;
- cache[item].offset = offset;
- cache[item].dirty = FALSE;
-
- if (!(item <= 0 || xFiles_CacheCmp(cache[item-1].owner, cache[item-1].offset, item) < 0) ||
- !(item >= cacheUsed-1 || xFiles_CacheCmp(cache[item+1].owner, cache[item+1].offset, item) > 0))
- {
- unsigned i;
-
- for (i = 0; i < cacheUsed; i++)
- {
- TRACE("%3d: %08x, %08x, %3d, %3d%s\n", i, cache[item].owner, cache[item].offset,
- cache[item].prev, cache[item].next,
- i == item ? " *" : "");
- }
-
- TRACE("xFiles_CacheEnsure(%p, %08x, %p, %d)\n", pInfo, offset, pItem, noRead);
- TRACE("Destroying cache\n");
-
- cacheUsed = 1; /* just destroy it */
- cacheHead = cacheTail = 0;
- cache[0].prev = cache[0].next = -1;
- item = 0;
- }
-
- *pItem = item;
-
- if (noRead)
- return NULL;
-
- return xFiles_rawRead(pInfo, cache[item].buffer, offset, xFiles_CACHECHUNKSIZE);
- }
-
- _kernel_oserror *xFiles_read(xFiles_info *pInfo, void *pBuffer, unsigned pos, unsigned size)
- {
-
- _kernel_oserror *err;
- int item;
- unsigned start, end;
- unsigned bufPos;
- char *outPtr;
- unsigned fragSize, totalSize;
- unsigned pendingStart, pendingSize;
-
-
- #ifndef NOCACHE
- if (!cache)
- #endif
- return xFiles_rawRead(pInfo, pBuffer, pos, size);
-
- xFiles_CacheCheck();
-
- /*TRACE("xFiles_read(%p, %p, %08x, %08x)\n", pInfo, pBuffer, pos, size);*/
-
- if (size == 0)
- return NULL;
-
- /* Set about reading it through the cache */
-
- start = roundDown(pos);
- end = roundUp(pos + size);
- bufPos = pos - start;
- outPtr = (char *) pBuffer;
- totalSize = size;
-
- ASSERT(start < end);
- ASSERT(bufPos < xFiles_CACHECHUNKSIZE);
-
- if (size > xFiles_OK2CACHE)
- {
- /* Large transfer: check each component block for a cache hit */
-
- pendingStart = pos;
- pendingSize = 0;
-
- while (start < end)
- {
- item = xFiles_CacheLookup(pInfo, start);
-
- fragSize = _min(xFiles_CACHECHUNKSIZE - bufPos, totalSize);
-
- if (item != -1)
- {
- if (pendingSize != 0)
- {
- if (err = xFiles_rawRead(pInfo, outPtr, pendingStart, pendingSize), err)
- return err;
-
- pendingStart += pendingSize;
- outPtr += pendingSize;
- pendingSize = 0;
- }
-
- ASSERT(cache[item].buffer >= buffer);
- ASSERT(cache[item].buffer < buffer + xFiles_CACHECHUNKSIZE * cacheSize);
- memcpy(outPtr, cache[item].buffer + bufPos, fragSize);
- outPtr += fragSize;
- pendingStart += fragSize;
- }
- else
- pendingSize += fragSize;
-
- totalSize -= fragSize;
- start += xFiles_CACHECHUNKSIZE;
- bufPos = 0;
- }
-
- if (pendingSize != 0)
- {
- if (err = xFiles_rawRead(pInfo, outPtr, pendingStart, pendingSize), err)
- return err;
- }
- }
- else
- {
- while (start < end)
- {
- /*TRACE(" reading chunk at %08x through cache\n", start);*/
-
- if (err = xFiles_CacheEnsure(pInfo, start, &item, FALSE), err)
- return err;
-
- fragSize = _min(xFiles_CACHECHUNKSIZE - bufPos, totalSize);
-
- ASSERT(outPtr >= (char *) pBuffer);
- ASSERT(outPtr + fragSize <= (char *) pBuffer + size);
-
- memcpy(outPtr, cache[item].buffer + bufPos, fragSize);
-
- outPtr += fragSize;
- totalSize -= fragSize;
- start += xFiles_CACHECHUNKSIZE;
- bufPos = 0;
- }
- }
-
- #ifndef NOWRITEBEHIND
- xFiles__timer = 200;
- #endif
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_write(xFiles_info *pInfo, void *pBuffer, unsigned pos, unsigned size)
- {
- int item;
- unsigned start, end;
- unsigned bufPos;
- char *outPtr;
- unsigned fragSize;
- unsigned totalSize;
- unsigned fileSize;
- BOOL noRead;
- _kernel_oserror *err;
- unsigned pendingStart, pendingSize;
-
- xFiles_CacheCheck();
-
-
- /*TRACE("xFiles_write(%p, %p, %08x, %08x)\n", pInfo, pBuffer, pos, size);*/
-
- if (size == 0)
- return NULL;
-
- #ifndef NOCACHE
- if (!cache)
- #endif
- return xFiles_rawWrite(pInfo, pBuffer, pos, size);
-
- start = roundDown(pos);
- end = roundUp(pos + size);
- bufPos = pos - start;
- outPtr = (char *) pBuffer;
- totalSize = size;
- ASSERT(start < end);
- ASSERT(bufPos < xFiles_CACHECHUNKSIZE);
-
- if (size > xFiles_OK2CACHE)
- {
- /* Large transfer: check each component block for a cache hit and update
- * the cache too if necessary (bus snooping).
- */
-
- pendingStart = pos;
- pendingSize = 0;
-
- while (start < end)
- {
- item = xFiles_CacheLookup(pInfo, start);
-
- fragSize = _min(xFiles_CACHECHUNKSIZE - bufPos, totalSize);
-
- if (item != -1)
- {
- if (pendingSize != 0)
- {
- if (err = xFiles_rawWrite(pInfo, outPtr, pendingStart, pendingSize), err)
- return err;
-
- pendingStart += pendingSize;
- outPtr += pendingSize;
- pendingSize = 0;
- }
-
- ASSERT(cache[item].buffer >= buffer);
- ASSERT(cache[item].buffer < buffer + xFiles_CACHECHUNKSIZE * cacheSize);
- memcpy(cache[item].buffer + bufPos, outPtr, fragSize);
- outPtr += fragSize;
- pendingStart += fragSize;
- cache[item].dirty = TRUE;
- }
- else
- pendingSize += fragSize;
-
- totalSize -= fragSize;
- start += xFiles_CACHECHUNKSIZE;
- bufPos = 0;
- }
-
- if (pendingSize != 0)
- {
- if (err = xFiles_rawWrite(pInfo, outPtr, pendingStart, pendingSize), err)
- return err;
- }
- }
- else
- {
- if (err = xFiles_getLength(pInfo, &fileSize), err)
- return err;
-
- if (pos + size > fileSize)
- {
- fileSize = xFiles_roundUp(pInfo, pos + size);
- if (err = xFiles_setLength(pInfo, fileSize), err)
- return err;
- }
-
- /* Small transfer: ensure each component block is cached and write to both
- * the cached block and to disc.
- */
-
- while (start < end)
- {
- /* Work out whether we need to read before write */
-
- fragSize = _min(xFiles_CACHECHUNKSIZE - bufPos, totalSize);
-
- noRead = (bufPos == 0 && fragSize == xFiles_CACHECHUNKSIZE);
-
- /*TRACE(" writing chunk at %08x through cache (fragSize = %08x, noRead = %s)\n",
- start, fragSize, noRead ? "TRUE" : "FALSE");*/
-
- if (err = xFiles_CacheEnsure(pInfo, start, &item, noRead), err)
- return err;
-
- ASSERT(outPtr >= (char *) pBuffer);
- ASSERT(outPtr + fragSize <= (char *) pBuffer + size);
-
- memcpy(cache[item].buffer + bufPos, outPtr, fragSize);
-
- #if 1
- cache[item].dirty = TRUE;
- #else
- if (err = xFiles_rawWrite(pInfo, cache[item].buffer, cache[item].offset, xFiles_CACHECHUNKSIZE), err)
- return err;
- #endif
-
- outPtr += fragSize;
- totalSize -= fragSize;
- start += xFiles_CACHECHUNKSIZE;
- bufPos = 0;
- }
-
- }
-
- #ifndef NOWRITEBEHIND
- xFiles__timer = 200;
- #endif
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_Commit(xFiles_info *pInfo)
- {
- _kernel_oserror *err;
-
- if (err = xFiles_squashFile(pInfo, FALSE), err)
- return err;
-
- #ifdef NOWRITEBEHIND
- if (err = xFiles_Flush(), err)
- return err;
- #endif
-
- return NULL;
- }
-
- /* Force the image file to truncate by
- * issuing the appropriate service call
- */
-
- _kernel_oserror *xFiles_Truncate(xFiles_info *pInfo)
- {
- _kernel_oserror *err;
- _kernel_swi_regs regs;
- char name[257];
-
- if (pInfo->openList.head != NULL)
- {
- /*TRACE("Don't want to truncate image which has open files\n");*/
- return NULL;
- }
-
- regs.r[0] = 7;
- regs.r[1] = pInfo->fileHandle;
- regs.r[2] = (int) name;
- regs.r[5] = 256;
-
- if (err = _kernel_swi(OS_Args, ®s, ®s), err)
- return err;
-
- /* Now force the named image to close. This will cause X-Files to reenter, so
- * be ready!
- */
-
- /*TRACE("Closing %s\n", name);*/
-
- regs.r[1] = 0x68;
- regs.r[2] = (int) name;
- regs.r[3] = 0;
-
- if (err = _kernel_swi(OS_ServiceCall, ®s, ®s), err)
- return err;
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_Flush(void)
- {
- int i;
- _kernel_oserror *err;
- _kernel_swi_regs regs;
- xFiles_info *pInfo;
-
- for (i = 0; i < cacheUsed; i++)
- {
- if (cache[i].offset != 0xFFFFFFFF && cache[i].dirty)
- {
- /*TRACE("Flush(2) %08x, %08x, %08x\n",
- cache[i].owner, cache[i].buffer, cache[i].offset);*/
-
- if (err = xFiles_rawWrite((xFiles_info *) cache[i].owner,
- cache[i].buffer, cache[i].offset,
- xFiles_CACHECHUNKSIZE), err)
- return err;
-
- cache[i].dirty = FALSE;
- }
- }
-
- for (pInfo = (xFiles_info *) xFiles_openFiles.head; pInfo; pInfo = (xFiles_info *) pInfo->li.next)
- {
- regs.r[0] = 255;
- regs.r[1] = pInfo->fileHandle;
-
- if (err = _kernel_swi(OS_Args, ®s, ®s), err)
- return err;
- }
-
-
- return NULL;
- }
-
- _kernel_oserror *xFiles_WriteBehind(_kernel_swi_regs *regs)
- {
- xFiles_info *pInfo, *pNext;
-
- (void) regs;
-
- #ifndef NOWRITEBEHIND
-
- (void) xFiles_Flush();
-
- for (pInfo = (xFiles_info *) xFiles_openFiles.head; pInfo; pInfo = pNext)
- {
- pNext = (xFiles_info *) pInfo->li.next;
-
- if (pInfo->flags & xFiles_fNeedTruncate)
- {
- pInfo->flags &= ~xFiles_fNeedTruncate;
- (void) xFiles_Truncate(pInfo);
-
- /* Beware: pInfo might not be valid now */
- }
- }
-
- #endif
-
- return NULL;
- }
-
- extern void entry_WriteBehind(void);
-
- #pragma -s1
- _kernel_oserror *xFiles_Ticker(_kernel_swi_regs *regs)
- {
- (void) regs;
-
- if (xFiles__timer > 0 && --xFiles__timer == 0)
- {
- _kernel_swi_regs regs;
-
- regs.r[0] = (int) entry_WriteBehind;
- regs.r[1] = (int) wsp;
-
- (void) _kernel_swi(OS_AddCallBack, ®s, ®s);
- }
-
- return NULL;
- }
- #pragma -s0
-