home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/alerts.h>
-
- static char rcsid [] = "$Id: globals.c,v 3.6 95/12/16 18:36:41 Martin_Apel Exp $";
-
- #undef GLOBAL
- #define GLOBAL
-
- #include "defs.h"
-
- #define ERROR_STACK 2000L
-
- PRIVATE UWORD ErrorLevel;
- PRIVATE char *ErrorString;
- PRIVATE struct Task *ErringTask;
- PRIVATE char ErrorBuffer [500];
- PRIVATE ULONG ErrorHandlerStack [ERROR_STACK/sizeof (ULONG)];
- PRIVATE struct Task ErrorHandlerTask;
-
- PRIVATE struct EasyStruct ErrorReq =
- {
- sizeof (struct EasyStruct),
- NULL,
- PROGNAME,
- ErrorBuffer,
- NULL
- };
-
- PRIVATE APTR ErrorMsg [] =
- {
- NULL, /* SUCCESS */
- NULL, /* ERR_MSG_POSTED */
- msgNotEnoughMem,
- msgNoPagingFile,
- msgNoSpace,
- msgFailedIo,
- msgFileIsDir,
- msgInternal,
- msgInhibitFailed,
- msgWrongBlocksize,
- msgNoDiskinfo,
- msgNotValidated,
- msgOutOfBounds,
- msgNoFFS,
- msgNoConfigFile,
- msgCorruptCfgFile,
- msgVolumeNotFound,
- msgLowVersion,
- msgNoDOS,
- msgNoIntuition,
- msgNoGfx,
- msgNoUtility,
- msgNoExpansion,
- msgNoCommodities,
- msgWrongCPU,
- msgNoAddrSpace,
- msgNoPrefs,
- msgNoStatwindow,
- msgNoRexx,
- msgDynMapFailed
- };
-
-
- /*********************************************************************/
-
- PRIVATE void ErrorTask (void)
-
- {
- PRINT_DEB ("ErrorTask alive", 0L);
-
- sprintf (ErrorBuffer, GetVMMString (msgGenericError),
- (ErrorLevel == ERR_NOERROR) ? GetVMMString (msgMessage) : GetVMMString (msgError),
- ErringTask->tc_Node.ln_Name, ErrorString);
-
- if (ErrorLevel == ERR_FATAL)
- ErrorReq.es_GadgetFormat = GetVMMString (msgReboot);
- else
- ErrorReq.es_GadgetFormat = GetVMMString (msgOK);
-
- EasyRequestArgs (NULL, &ErrorReq, NULL, NULL);
-
- if (ErrorLevel == ERR_FATAL)
- {
- PRINT_DEB ("Fatal error. Rebooting...", 0L);
- ColdReboot ();
- }
- else
- PRINT_DEB ("Continuing after error", 0L);
- ENABLE_VM; /* Corresponding DISABLE_VM has been done by ReportError */
- }
-
- /*********************************************************************/
-
- void ReportError (char *error_string, UWORD error_level)
-
- {
- PRINT_DEB ("ReportError called", 0L);
-
- DISABLE_VM;
- if (FindTask (ERR_NAME) != NULL)
- {
- PRINT_DEB ("Couldn't post error message. Error task already existed", 0L);
- return;
- }
-
- ErrorHandlerTask.tc_Node.ln_Type = NT_TASK;
- ErrorHandlerTask.tc_Node.ln_Name = ERR_NAME;
- ErrorHandlerTask.tc_Node.ln_Pri = 10;
- ErrorHandlerTask.tc_SPReg = &(ErrorHandlerStack [ERROR_STACK/sizeof (ULONG) - 1]);
- ErrorHandlerTask.tc_SPLower = &(ErrorHandlerStack [0]);
- ErrorHandlerTask.tc_SPUpper = &(ErrorHandlerStack [ERROR_STACK/sizeof (ULONG) - 1]);
- NewList (&(ErrorHandlerTask.tc_MemEntry));
-
- ErrorLevel = error_level;
- ErringTask = FindTask (NULL);
- ErrorString = error_string;
-
- PRINT_DEB ("Creating error task", 0L);
- if (AddTask (&ErrorHandlerTask, ErrorTask, NULL) == NULL)
- {
- PRINT_DEB ("Error creating error task", 0L);
- if (ErrorLevel == ERR_FATAL)
- Alert (AT_DeadEnd | AG_IOError | AN_Unknown);
- else
- Alert (AT_Recovery | AG_IOError | AN_Unknown);
- }
- PRINT_DEB ("Successfully created error task", 0L);
- }
-
- /***********************************************************************/
-
- void InitError (int num)
-
- {
- if (num == ERR_MSG_POSTED)
- return;
-
- if (num > ERR_MAX_ERRNO)
- {
- PRINT_DEB ("InitError: Illegal error number %ld", (ULONG)num);
- #ifdef DEBUG
- ColdReboot ();
- #endif
- num = ERR_INTERNAL;
- }
-
- ReportError (GetVMMString (ErrorMsg [num]), ERR_CONTINUE);
- }
-
- /***********************************************************************/
-
- void RunTimeError (int num)
-
- {
- InitError (num);
- }
-
- /***********************************************************************/
-
- void FatalError (int num)
-
- {
- if (num > ERR_MAX_ERRNO)
- {
- PRINT_DEB ("FatalError: Illegal error number %ld", (ULONG)num);
- #ifdef DEBUG
- ColdReboot ();
- #endif
- num = ERR_INTERNAL;
- }
-
- ReportError (ErrorMsg [num], ERR_FATAL);
- Wait (0L); /* Wait forever */
- }
-
- /***********************************************************************/
-
- void *AllocAligned (ULONG size, ULONG flags, ULONG alignment, ULONG priority)
-
- /* Allocates "size" bytes aligned at an "alignment" boundary.
- * "alignment" must be a power of two and larger than the minimum
- * memory size (currently 8 bytes).
- * Supported flags are MEMF_PUBLIC, MEMF_CHIP, MEMF_FAST, MEMF_REVERSE.
- * Priority is a hint on how much time should be spent in AllocAligned.
- * 0 is the highest priority, it means: Do whatever you can to make
- * memory available. For lower values, 'priority' gives the number of
- * bytes which must be available in a memory region to make AllocAligned
- * step into it and search.
- */
- {
- struct MemHeader *mh;
- struct MemChunk **cur_mc,
- **chosen_mc;
-
- #ifdef DEBUG
- if (size % alignment != 0)
- {
- ReportError ("Internal error in AllocAligned:\n"
- "size not multiple of alignment", ERR_CONTINUE);
- return (NULL);
- }
- #endif
-
- Forbid ();
- CHECK_CONSISTENCY;
- chosen_mc = NULL;
- for (mh = (struct MemHeader*)SysBase->MemList.lh_Head;
- mh->mh_Node.ln_Succ != NULL;
- mh = (struct MemHeader*)mh->mh_Node.ln_Succ)
- {
- /* Check flags */
- if (((mh->mh_Attributes & flags) == (flags & (MEMF_CHIP | MEMF_FAST | MEMF_PUBLIC)))
- && (mh->mh_Free > priority))
- {
- if (flags & MEMF_REVERSE)
- {
- /* Use last fitting chunk */
- for (cur_mc = &(mh->mh_First); *cur_mc != NULL;
- cur_mc = &((*cur_mc)->mc_Next))
- {
- if (((*cur_mc)->mc_Bytes >= size) &&
- (ALIGN_UP ((ULONG)*cur_mc, alignment) + size <=
- (ULONG)*cur_mc + (*cur_mc)->mc_Bytes))
- chosen_mc = cur_mc;
- }
- }
- else
- {
- /* Use first fitting chunk */
- for (cur_mc = &(mh->mh_First); *cur_mc != NULL;
- cur_mc = &((*cur_mc)->mc_Next))
- {
- if (((*cur_mc)->mc_Bytes >= size) &&
- (ALIGN_UP ((ULONG)*cur_mc, alignment) + size <=
- (ULONG)*cur_mc + (*cur_mc)->mc_Bytes))
-
- {
- chosen_mc = cur_mc;
- break;
- }
- }
- }
- if (chosen_mc != NULL)
- break;
- }
- }
-
- if (chosen_mc == NULL)
- {
- void *tmp_buffer = NULL;
-
- CHECK_CONSISTENCY;
- if (priority == 0L)
- {
- PRINT_DEB ("AllocAligned: Executing avail flush", 0L);
- if (FindTask (NULL) == PageHandlerTask)
- {
- PRINT_DEB ("Pagehandler is executing avail flush !!!", 0L);
- tmp_buffer = DoOrigAllocMem (2 * size, flags);
- }
- else
- tmp_buffer = AllocMem (2 * size, flags);
-
- if (tmp_buffer != NULL)
- {
- FreeMem (tmp_buffer, 2 * size);
- tmp_buffer = AllocAligned (size, flags, alignment, 1L);
- }
- }
- Permit ();
- return (tmp_buffer);
- }
- else
- {
- ULONG start_alloc;
- struct MemChunk *new_chunk,
- *tmp_chunk;
- ULONG chunk_size;
-
- tmp_chunk = *chosen_mc;
- /* Found a fitting chunk. Do the allocation */
- if (flags & MEMF_REVERSE)
- {
- start_alloc = ALIGN_DOWN ((ULONG)tmp_chunk + tmp_chunk->mc_Bytes, alignment)
- - size;
- }
- else
- start_alloc = ALIGN_UP ((ULONG)tmp_chunk, alignment);
-
- chunk_size = tmp_chunk->mc_Bytes - size; /* size of remaining mem */
-
- if ((ULONG)tmp_chunk < start_alloc)
- {
- /* Make this chunk smaller */
- tmp_chunk->mc_Bytes = start_alloc - (ULONG)tmp_chunk;
- chunk_size -= tmp_chunk->mc_Bytes;
- chosen_mc = &(tmp_chunk->mc_Next);
- }
-
- if (chunk_size > 0)
- {
- new_chunk = (struct MemChunk*)(start_alloc + size);
- new_chunk->mc_Next = tmp_chunk->mc_Next;
- new_chunk->mc_Bytes = chunk_size;
- *chosen_mc = new_chunk;
- }
- else
- *chosen_mc = tmp_chunk->mc_Next;
-
- mh->mh_Free -= size;
-
- CHECK_CONSISTENCY;
- Permit ();
- return ((void*)start_alloc);
- }
- }
-
- /***********************************************************************/
-
- #define isspace(c) (((c)==' ') || ((c) == '\t') || ((c) == '\n'))
-
- void GetNthString (char *from, char *to, int n)
-
- {
- /* Extracts the nth string in the line "from" and copies it to "to".
- * If the nth string does not exist 'to' is set to an empty string.
- */
- char *tmp1, *tmp2;
-
- tmp1 = from;
- tmp2 = to;
- while (*tmp1 != 0 && isspace (*tmp1)) tmp1++; /* skip leading whitespace */
-
- while (--n > 0)
- {
- while (*tmp1 != 0 && !isspace (*tmp1)) tmp1++; /* skip word */
- while (*tmp1 != 0 && isspace (*tmp1)) tmp1++; /* skip blanks */
- }
-
- while (*tmp1 != 0 && !isspace(*tmp1)) *tmp2++ = *tmp1++;
- *tmp2 = 0;
- }
-
- /***********************************************************************/
-
- void StrToHex (char *string, ULONG *val)
-
- {
- char *tmp;
-
- tmp = string;
- *val = 0;
- while (*tmp != 0 && isspace(*tmp))
- tmp++;
-
- while (*tmp != 0 && !isspace (*tmp))
- {
- *val = (*val << 4);
-
- if (*tmp >= '0' && *tmp <= '9')
- *val += *tmp - '0';
- else if (*tmp >= 'a' && *tmp <= 'f')
- *val += *tmp - 'a' + 10;
- else if (*tmp >= 'A' && *tmp <= 'F')
- *val += *tmp - 'F' + 10;
- else
- {
- return;
- }
-
- tmp++;
- }
- }
-
- /***********************************************************************/
-
- void EmptyPageCollector (void)
-
- /* Routine for a task that is created after a specified number of FreeMems on
- * virtual memory. It traverses the memory list for virtual memory and
- * frees the pages and frames of unused pages.
- */
- {
- struct VMMsg *FreeMsg;
- UWORD ReplySignal;
- struct MemChunk *chunk;
-
- PRINT_DEB ("EmptyPageCollector running", 0L);
-
- if ((FreeMsg = AllocMem (sizeof (struct VMMsg), MEMF_PUBLIC)) == NULL)
- return;
-
- ReplySignal = AllocSignal (-1L); /* Guaranteed to succeed */
- FreeMsg->VMSender = FindTask (NULL);
- FreeMsg->VMCommand = VMCMD_FreePages;
- FreeMsg->ReplySignal = ReplySignal;
-
- PRINT_DEB ("Obtaining VM sema", 0L);
- OBTAIN_VM_SEMA;
- PRINT_DEB ("VM sema obtained", 0L);
-
- for (chunk = VirtMem->mh_First; chunk != NULL; chunk = chunk->mc_Next)
- {
- if ((ULONG)chunk + chunk->mc_Bytes > ALIGN_UP ((ULONG)(chunk + 1) + PAGESIZE, PAGESIZE))
- {
- /* There is at least one page contained in this are */
- FreeMsg->FreeAddress = (ULONG)(chunk + 1);
- FreeMsg->FreeSize = chunk->mc_Bytes - sizeof (struct MemChunk);
- PutMsg (PageHandlerPort, (struct Message*) FreeMsg);
- Wait (1L << ReplySignal);
- }
- }
-
- PRINT_DEB ("Releasing VM sema", 0L);
- RELEASE_VM_SEMA;
- FreeMem (FreeMsg, sizeof (struct VMMsg));
- FreeSignal ((LONG)ReplySignal);
-
- VMFreeCounter = COLLECT_INTERVAL;
- PRINT_DEB ("EmptyPageCollector terminating", 0L);
- }
-