⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spacebank.c

📁 C++ 编写的EROS RTOS
💻 C
字号:
/* * Copyright (C) 1998, 1999, Jonathan Adams. * Copyright (C) 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* SpaceBank -- Controls allocation of nodes and pages. * * 7/2/97 -- Rebuilt from scratch to incorporate Object Frames, *         the SuperRange key, etc.  Wheee. *           This file holds the main routine, crt0 intializers, *         and little else. */#include <eros/target.h>#include <eros/RangeKey.h>#include <eros/NodeKey.h>#include <eros/ProcessKey.h>#include <eros/ProcessToolKey.h>#include <eros/Invoke.h>#include <eros/StdKeyType.h>#include <domain/SpaceBankKey.h>#include <domain/domdbg.h>#include <domain/Runtime.h>#include "misc.h"#include "debug.h"#include "constituents.h"#include "spacebank.h"#include "Bank.h"#include "ObjSpace.h"#include "malloc.h"uint32_t objects_per_frame[OT_NUM_TYPES];uint32_t objects_map_mask[OT_NUM_TYPES];static const char *type_names[OT_NUM_TYPES];/* functions */intProcessRequest(Message *argmsg);/* ProcessRequest: *     Called to interpret and respond to each message received.   *   It is passed the Bank the message is for and the Message recieved. *   The response, success or failure, is put into the argmsg argument,  *   and ProcessRequest should return 1 when it is finished. *  *     Note that Bank can == NULL, which is prob. a failure. * *     If 0 is ever returned, the SpaceBank process will quit.  This is a  *   *bad thing*, and should never happen. (consider not allowing?) */void InitSpaceBank(void);/**Handle the stack stuff**/const uint32_t __rt_stack_pointer = 0x100000;uint32_t __rt_unkept = 1;intmain(void){  Message msg;  char buff[sizeof(struct bank_limits) + 2]; /* two extra for failure						detection */    node_copy(KR_CONSTIT, KC_PRIMERANGE, KR_SRANGE);  node_copy(KR_CONSTIT, KC_RETURNER, KR_RETURNER);  node_copy(KR_CONSTIT, KC_VOLSIZE, KR_VOLSIZE);  node_copy(KR_CONSTIT, KC_OSTREAM, KR_OSTREAM);  msg.snd_invKey = KR_VOID;  msg.snd_key0 = KR_VOID;  msg.snd_key1 = KR_VOID;  msg.snd_key2 = KR_VOID;  msg.snd_key3 = KR_VOID;  msg.snd_data = 0;  msg.snd_len = 0;  msg.snd_code = 0;  msg.snd_w1 = 0;  msg.snd_w2 = 0;  msg.snd_w3 = 0;  msg.rcv_key0 = KR_ARG0;  msg.rcv_key1 = KR_ARG1;  msg.rcv_key2 = KR_ARG2;  msg.rcv_key3 = KR_RETURN;  msg.rcv_len = sizeof(buff);  msg.rcv_data = buff;  msg.rcv_code = 0;  msg.rcv_w1 = 0;  msg.rcv_w2 = 0;  msg.rcv_w3 = 0;  DEBUG(init) kdprintf(KR_OSTREAM, "spacebank: calling InitSpaceBank()\n");  /* Initialization is not permitted to fail -- this would constitute     an unrunnable system! */  InitSpaceBank();    DEBUG(init) kdprintf(KR_OSTREAM, "spacebank: accepting requests()\n");  for(;;) {#ifdef TIMESTAMPS    uint64_t timestamp_before;    uint64_t timestamp_taken;#endif    msg.rcv_len = sizeof(buff); /* reset receive length */    RETURN(&msg);#ifdef USE_RETURNER    msg.snd_invKey = KR_RETURNER;    msg.snd_key3 = KR_RETURN;#else        msg.snd_invKey = KR_RETURN;#endif#ifdef TIMESTAMPS    timestamp_before = rdtsc();#endif    (void) ProcessRequest(&msg);#ifdef TIMESTAMPS    timestamp_taken = rdtsc() - timestamp_before;        kprintf(KR_OSTREAM,	     "SpaceBank:  Request %02x took "DW_HEX" cycles.\n",	     msg.rcv_code,	     DW_HEX_ARG(timestamp_taken));    #endif  }}static int request_ob_type[] = {  -1,				/* none */   OT_Node,			/* OC_SpaceBank_Alloc1Node */  OT_Node,			/* OC_SpaceBank_Alloc2Nodes */  OT_Node,			/* OC_SpaceBank_Alloc3Nodes */  OT_Node,			/* OC_SpaceBank_Reclaim1Node */  OT_Node,			/* OC_SpaceBank_Reclaim2Nodes */  OT_Node,			/* OC_SpaceBank_Reclaim3Nodes */  OT_Node,			/* OC_SpaceBank_ReclaimNodesFromNode */  OT_Node,			/* OC_SpaceBank_SeverNode */	        OT_DataPage,			/* OC_SpaceBank_Alloc1DataPage */  OT_DataPage,			/* OC_SpaceBank_Alloc2DataPages */  OT_DataPage,			/* OC_SpaceBank_Alloc3DataPages */  OT_DataPage,			/* OC_SpaceBank_Reclaim1DataPage */  OT_DataPage,			/* OC_SpaceBank_Reclaim2DataPages */  OT_DataPage,			/* OC_SpaceBank_Reclaim3DataPages */  OT_DataPage,			/* OC_SpaceBank_ReclaimDataPagesFromNode */  OT_DataPage,			/* OC_SpaceBank_SeverDataPage */	        -1,-1,-1,-1,-1,-1,-1,-1,      /* 16-23, unused */	        OT_Node,			/* OC_SpaceBank_Identify1Node */  OT_Node,			/* OC_SpaceBank_Identify2Nodes */  OT_Node,			/* OC_SpaceBank_Identify3Nodes */  OT_DataPage,			/* OC_SpaceBank_Identify1DataPage */  OT_DataPage,			/* OC_SpaceBank_Identify2DataPages */  OT_DataPage,			/* OC_SpaceBank_Identify3DataPages */};/* General note on workings of functions called by ProcessRequest: * *    Before ProcessRequest calls a function, it zeroes the code of the *  snd message structure.  It only modifies the structure if the *  function returns a value != RC_OK.  This means if you can do a *  dispatch call to another key by mucking with the structure and *  returning RC_OK.  The resume key the Spacebank was called with is *  held in KR_RETURN. * */ intProcessRequest(Message *argmsg){  uint32_t result = RC_OK;  uint32_t code = argmsg->rcv_code;    Bank *bank = BankFromInvocation(argmsg);  BankPrecludes preclude = PrecludesFromInvocation(argmsg);      uint32_t count = 0;  argmsg->snd_len = 0;  argmsg->snd_w1 = 0;  argmsg->snd_w2 = 0;  argmsg->snd_w3 = 0;  argmsg->snd_key0 = KR_VOID;  argmsg->snd_key1 = KR_VOID;  argmsg->snd_key2 = KR_VOID;  argmsg->snd_code = RC_OK;  #ifdef PARANOID  if (preclude > BANKPREC_MASK) {    kpanic(KR_OSTREAM, "spacebank: bad preclude 0x%08x\n", preclude);    return 1;  }#endif    switch (code) {    /* ALLOCATIONS */  case OC_SpaceBank_Alloc3DataPages:  case OC_SpaceBank_Alloc3Nodes:    argmsg->snd_key2 = KR_ARG2;    count ++;    /* fall through */  case OC_SpaceBank_Alloc2DataPages:  case OC_SpaceBank_Alloc2Nodes:    argmsg->snd_key1 = KR_ARG1;    count ++;    /* fall through */  case OC_SpaceBank_Alloc1DataPage:  case OC_SpaceBank_Alloc1Node:    {            uint8_t type = request_ob_type[code];      count ++;      argmsg->snd_key0 = KR_ARG0;      result = BankAllocObjects(bank, type, count, KR_ARG0);      if (result != RC_OK) {	argmsg->snd_key0 = KR_VOID;	argmsg->snd_key1 = KR_VOID;	argmsg->snd_key2 = KR_VOID;      }      argmsg->snd_code = result;      DEBUG(realloc) {	if ( ((bank->allocs[OT_DataPage] % 20) == 0) ||	     ((bank->deallocs[OT_DataPage] % 20) == 0) )	  kprintf(KR_OSTREAM, "*%d pages allocd, %d deallocd\n",		  bank->allocs[OT_DataPage],		  bank->deallocs[OT_DataPage]		  );      }      break;    }  /* DEALLOCATIONS */  case OC_SpaceBank_Reclaim3DataPages:  case OC_SpaceBank_Reclaim3Nodes:    count++;    /* fall through */  case OC_SpaceBank_Reclaim2DataPages:  case OC_SpaceBank_Reclaim2Nodes:    count++;    /* fall through */  case OC_SpaceBank_Reclaim1DataPage:  case OC_SpaceBank_Reclaim1Node:    {      uint8_t type = request_ob_type[code];      count++;      result = BankDeallocObjects(bank, type, count, KR_ARG0);      if (result != RC_OK) {	DEBUG(dealloc)	  kdprintf(KR_OSTREAM, "Spacebank: dealloc of %s failed (0x%1x)\n",		   type_name(type),		   result);	argmsg->snd_code = result;      }      break;    }  case OC_SpaceBank_ReclaimDataPagesFromNode:  case OC_SpaceBank_ReclaimNodesFromNode:    {      uint32_t type;            /* verify that they actually passed us a node key */      if (range_identify(KR_SRANGE, KR_ARG0, &type, NULL) != RC_OK          || type != OT_Node) {        argmsg->snd_code = RC_RequestError;        break;      } else {	/* it's a node */	uint32_t slot;	uint32_t mask = 0;		for (slot = 0; slot < EROS_NODE_SIZE; slot++) {	  uint32_t result;		  result = node_copy(KR_ARG0, slot, KR_ARG1);	  if (result != RC_OK) {	    DEBUG(dealloc)	      kdprintf(KR_OSTREAM,		       "Spacebank: copy of %s from slot %d failed (0x%1x)\n",		       type_name(type),		       slot,		       result);	    mask |= (1u << slot);	    continue;	  }	  result = BankDeallocObjects(bank, type, 1, KR_ARG1);	  if (result != RC_OK) {	    DEBUG(dealloc)	      kdprintf(KR_OSTREAM,		       "Spacebank: dealloc of %s in slot %d failed (0x%1x)\n",		       type_name(type),		       slot,		       result);	    mask |= (1u << slot);	    continue;	  }	}      	argmsg->snd_code = result;	break;      }    }  /* IDENTIFICATIONS */  case OC_SpaceBank_Identify3DataPages:  case OC_SpaceBank_Identify3Nodes:    count++;    /* fall through */  case OC_SpaceBank_Identify2DataPages:  case OC_SpaceBank_Identify2Nodes:    count++;    /* fall through */  case OC_SpaceBank_Identify1DataPage:  case OC_SpaceBank_Identify1Node:    {      uint8_t type = request_ob_type[code];      count++;      result = BankIdentifyObjects(bank, type, count, KR_ARG0);      if (result != RC_OK) {	argmsg->snd_code = result;      }      break;    }  case OC_SpaceBank_SeverDataPage:  case OC_SpaceBank_SeverNode:    {#if 0      uint8_t type = request_ob_type[code];#endif      /* not implemented yet */      argmsg->snd_code = RC_UnknownRequest;      break;    }  case OC_SpaceBank_Preclude:    {      preclude |= argmsg->rcv_w3;      if (preclude > BANKPREC_MASK) {	argmsg->snd_code = RC_RequestError;	break;      }      result = BankCreateKey(bank, preclude, KR_ARG0);      if (result == RC_OK) argmsg->snd_key0 = KR_ARG0;      break;    }  case OC_Destroy:    {      /* destroy bank, returning space to parent */      if (BANKPREC_CAN_DESTROY(preclude))	argmsg->snd_code = BankDestroyBankAndStorage(bank, false);      else	argmsg->snd_code = RC_UnknownRequest;      break;    }  case OC_SpaceBank_DestroyBankAndSpaces:    {      /* destroy bank, deallocating space */      if (BANKPREC_CAN_DESTROY(preclude))	argmsg->snd_code = BankDestroyBankAndStorage(bank, true);      else	argmsg->snd_code = RC_UnknownRequest;      break;    }         case OC_SpaceBank_SetLimits:    {      if ( !BANKPREC_CAN_MOD_LIMIT(preclude) ) 	argmsg->snd_code = RC_UnknownRequest;      else if (argmsg->rcv_len != sizeof(struct bank_limits))	argmsg->snd_code = RC_RequestError;      else {	struct bank_limits *limPtr = (struct bank_limits *)argmsg->rcv_data;	argmsg->snd_code = BankSetLimits(bank, limPtr);      }      break;    }  case OC_SpaceBank_GetLimits:    {      static struct bank_limits retLimits;      /* static so it survives the return */      /* FIXME: can this be precluded? */      argmsg->snd_code = BankGetLimits(bank, &retLimits);      if (argmsg->snd_code == RC_OK) {	argmsg->snd_len = sizeof(retLimits);	argmsg->snd_data = (void *)&retLimits;      }      break;    }  case OC_SpaceBank_CreateChild:    {      argmsg->snd_code = BankCreateChild(bank, KR_ARG0);      if (argmsg->snd_code == RC_OK) argmsg->snd_key0 = KR_ARG0;            break;    }   case OC_SpaceBank_VerifyBank:    {      uint32_t brandMatches;            /* verify that KR_ARG0 is a key to a valid spacebank */      /* use my domain key to create the brand key */      result = process_make_start_key(KR_SELF,				     SB_BRAND_KEYDATA,				     KR_TMP);      if (result != RC_OK) {	kpanic(KR_OSTREAM,	       "SpaceBank: VerifyBank failed to create brand key!\n");      }      /* get the DomainTool key */      node_copy(KR_CONSTIT, KC_DOMTOOL, KR_TMP2);            /* use it to replace the brand key with the node key from       * KR_ARG0 (assuming KR_ARG0 is a valid spacebank key)       */      result = pt_identsegkpr(KR_TMP2, KR_ARG0, KR_TMP, KR_TMP, &brandMatches, 0);      if (result != RC_OK) {	kpanic(KR_OSTREAM,	       "SpaceBank: IdentSegKpr failed to match brand key! (0x%08x, %d)\n", result, brandMatches);      }      /* Return RC_OK if the operation succeeded (i.e. this is a valid       * segment key), -1 otherwise       */      argmsg->snd_code = RC_OK;      argmsg->snd_w1 = (result == RC_OK && brandMatches) ? 1 : 0;            break;    }  case OC_KeyType: /* Key type */    {      argmsg->snd_code = RC_OK;      argmsg->snd_w1 = AKT_SpaceBank;      break;    }  default:    {      argmsg->snd_code = RC_UnknownRequest;      break;    }  }  return 1;}voidInitSpaceBank(void){  int x;    DEBUG(init) kdprintf(KR_OSTREAM,	   "spacebank: spacebank initializing\n");  for (x = 0; x < OT_NUM_TYPES; x++) {    objects_per_frame[x] = 0u;    objects_map_mask[x] = 0u;    type_names[x] = "Invalid";  }#define SETUP_TYPE(type,perpage) \                             { \			       objects_per_frame[OT_ ## type] = perpage; \			       objects_map_mask[OT_ ## type] = \ 					              (1u << (perpage)) - 1; \			       type_names[OT_ ## type] = #type; \			     }  SETUP_TYPE(DataPage, 1u);  SETUP_TYPE(Node, EROS_NODES_PER_FRAME);#undef SETUP_TYPE#if 0  /* setup dummy types for printing */  SETUP_TYPE(UNKNOWN, 0);  SETUP_TYPE(INVALID, 0);#endif  DEBUG(init) kdprintf(KR_OSTREAM, "Initializing banks\n");  bank_init();  DEBUG(init) kdprintf(KR_OSTREAM, "Initializing ObjectSpace\n");  ob_init();			/* init master object space */  /* ^^^ also calls bank_init(); */  return; /* done */}const char *type_name(int t){  switch (t) {  case OT_DataPage:  case OT_Node:    return type_names[t];  default:    return "unknown";  }}boolvalid_type(int t){  switch (t) {  case OT_DataPage:  case OT_Node:    return true;  default:    return false;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -