📄 constructor.c
字号:
/* * Copyright (C) 1998, 1999, 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. *//* A constructor is responsible for building program instances. The * constructor holds copies of each entry of the constituents node. In * addition, it holds the target process' keeper key, address space * key, symbol table ke, and initial PC. * * BOOTSTRAP NOTE 1: * * To simplify system image construction, the constructor does some * minimal analysis at startup time. If KC_PROD_CON0 and KC_PROD_XCON * are not void, they are accepted as holding the product constituents, * and KC_DCC should hold the domain creator for the constituents. * * If initial constituents are found, the factory startup code assumes * that the factory should be initially sealed, and that no holes beyond * those that are apparent from the initial constituents are present, * and that KC_DCC is the actual domain creator. */#include <eros/target.h>#include <eros/Invoke.h>#include <eros/DiscrimKey.h>#include <eros/ReturnerKey.h>#include <eros/NodeKey.h>#include <eros/ProcessKey.h>#include <eros/Key.h>#include <eros/StdKeyType.h>#include <eros/ProcessState.h>#include <domain/domdbg.h>#include <domain/ConstructorKey.h>#include <domain/ProcessCreatorKey.h>#include <domain/PccKey.h>#include <domain/ProtoSpace.h>#include <domain/SpaceBankKey.h>#include <domain/Runtime.h>#include "constituents.h"uint32_t __rt_unkept = 1;#define KR_SCRATCH KR_APP(0)#define KR_RETURNER KR_APP(1)#define KR_OSTREAM KR_APP(2)#define KR_YIELDCRE KR_APP(3)#define KR_YIELDBITS KR_APP(4)#define KR_NEWDOM KR_APP(5)#define KR_PROD_CON0 KR_APP(6) /* product's constituents */#define KR_PROD_XCON KR_APP(7) /* product's extended constituents */#define KR_RO_YIELDBITS KR_APP(8) /* product's extended constituents */#define KR_ARG0 KR_ARG(0)#define KR_ARG1 KR_ARG(1)#define KR_ARG2 KR_ARG(2)#if 0#define KC_DISCRIM 0#define KC_RETURNER 1#define KC_OSTREAM 2#define KC_DCC 3#define KC_PROTOSPC 4#define KC_MYDOMCRE 5#define KC_PROD_CON0 14#define KC_PROD_XCON 15#endif/* Extended Constituents: */#define XCON_KEEPER 0#define XCON_ADDRSPACE 1#define XCON_SYMTAB 2#define XCON_PC 3#define DEBUG if (0)typedef struct { int frozen; int has_holes;} ConstructorInfo;voidCheckDiscretion(uint32_t kr, ConstructorInfo *ci){ uint32_t result; uint32_t keyInfo; uint32_t isDiscreet; node_copy(KR_CONSTIT, KC_DISCRIM, KR_SCRATCH); result = discrim_verify(KR_SCRATCH, kr, &isDiscreet); if (result == RC_OK && isDiscreet) return; node_copy(KR_CONSTIT, KC_YIELDCRE, KR_SCRATCH); result = proccre_amplify_gate(KR_SCRATCH, kr, KR_SCRATCH, 0, &keyInfo); if (result == RC_OK && keyInfo == 0) { uint32_t isDiscreet; /* This key is a requestor's key to a constructor. Ask the constructor if it is discreet */ result = constructor_is_discreet(kr, &isDiscreet); if (result == RC_OK && isDiscreet) return; } ci->has_holes = 1;}voidInitConstructor(ConstructorInfo *ci){ uint32_t result; uint32_t keyType; ci->frozen = 0; ci->has_holes = 0; node_copy(KR_CONSTIT, KC_OSTREAM, KR_OSTREAM); DEBUG kdprintf(KR_OSTREAM, "constructor init\n"); node_copy(KR_CONSTIT, KC_PROD_CON0, KR_PROD_CON0); result = key_kt(KR_PROD_CON0, &keyType, 0); if (result != RC_Void) { /* This is an initially frozen constructor. Use the provided constituents, and assume that KC_YIELDCRE already holds the proper domain creator. */ node_copy(KR_CONSTIT, KC_YIELDCRE, KR_YIELDCRE); node_copy(KR_CONSTIT, KC_PROD_CON0, KR_PROD_CON0); node_copy(KR_CONSTIT, KC_PROD_XCON, KR_PROD_XCON); ci->frozen = 1; } else { /* Build a new domain creator for use in crafting products */ /* use KR_YIELDCRE and KR_DISCRIM as scratch regs for a moment: */ node_copy(KR_CONSTIT, KC_PCC, KR_YIELDCRE); node_copy(KR_SELF, ProcSched, KR_SCRATCH); { Message msg; msg.snd_key0 = KR_BANK; msg.snd_key1 = KR_SCRATCH; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.snd_data = 0; msg.snd_len = 0; msg.snd_code = OC_PCC_CreateProcessCreator; msg.snd_invKey = KR_YIELDCRE; msg.rcv_key0 = KR_YIELDCRE; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_VOID; msg.rcv_len = 0; /* no data returned */ result = CALL(&msg); DEBUG kdprintf(KR_OSTREAM, "GOT DOMCRE Result is 0x%08x\n", result); } spcbank_buy_nodes(KR_BANK, 2, KR_PROD_CON0, KR_PROD_XCON, KR_VOID); } /* Create a runtime bits node appropriate for our yields: */ spcbank_buy_nodes(KR_BANK, 1, KR_YIELDBITS, KR_VOID, KR_VOID); node_clone(KR_YIELDBITS, KR_RTBITS); node_swap(KR_YIELDBITS, RKT_CREATOR, KR_YIELDCRE, KR_VOID); /* Now make the yieldbits key read-only. */ { uint16_t keyData; node_get_key_data(KR_YIELDBITS, &keyData); node_make_node_key(KR_YIELDBITS, SEGMODE_RO | EROS_PAGE_BLSS, KR_RO_YIELDBITS); } node_copy(KR_CONSTIT, KC_RETURNER, KR_RETURNER);}/* In spite of unorthodox fabrication, the constructor self-destructs in the usual way. */voidSepuku(){ /* FIX: giving up the constituent nodes breaks our products */ /* Give up the first constituent node. */ /* Give up the second constituent node */ spcbank_return_node(KR_BANK, KR_PROD_CON0); spcbank_return_node(KR_BANK, KR_PROD_XCON); spcbank_return_node(KR_BANK, KR_YIELDBITS); /* node_copy(KR_CONSTIT, KC_MYDOMCRE, KR_DOMCRE); */ node_copy(KR_CONSTIT, KC_PROTOSPACE, KR_PROD_CON0); spcbank_return_node(KR_BANK, KR_CONSTIT); /* Invoke the protospace with arguments indicating that we should be demolished as a small space domain */ protospace_destroy(KR_RETURNER, KR_PROD_CON0, KR_SELF, KR_CREATOR, KR_BANK, 1);}uint32_tMakeNewProduct(Message *msg){ uint32_t result; struct Registers regs; DEBUG kdprintf(KR_OSTREAM, "Making new product...\n"); result = proccre_create_process(KR_YIELDCRE, KR_ARG0, KR_NEWDOM); if (result != RC_OK) return result; /* NOTE that if proccre_create_process succeeded, we know it's a good space bank. */ /* Build a constiuents node, since we will need the scratch register later */ result = spcbank_buy_nodes(KR_ARG0, 1, KR_SCRATCH, KR_VOID, KR_VOID); if (result != RC_OK) goto destroy_product; /* clone the product constituents into the new constituents node: */ node_clone(KR_SCRATCH, KR_PROD_CON0); (void) process_swap_keyreg(KR_NEWDOM, KR_CONSTIT, KR_SCRATCH, KR_VOID); (void) process_swap_keyreg(KR_NEWDOM, KR_RTBITS, KR_RO_YIELDBITS, KR_VOID); DEBUG kdprintf(KR_OSTREAM, "Populate new domain\n"); (void) node_copy(KR_CONSTIT, KC_PROTOSPACE, KR_SCRATCH); /* Install protospace into the domain root: */ (void) process_swap(KR_NEWDOM, ProcAddrSpace, KR_SCRATCH, KR_VOID); DEBUG kdprintf(KR_OSTREAM, "Installed protospace\n"); /* Install the schedule key into the domain: */ (void) process_swap(KR_NEWDOM, ProcSched, KR_ARG1, KR_VOID); DEBUG kdprintf(KR_OSTREAM, "Installed sched\n"); /* Keeper constructor to keeper slot */ (void) node_copy(KR_PROD_XCON, XCON_KEEPER, KR_SCRATCH); (void) process_swap(KR_NEWDOM, ProcKeeper, KR_SCRATCH, KR_VOID); /* Fetch out the register values, mostly for the benefit of Retrieving the PC -- this prevents us from needing to hard-code the PC, which will inevitably change. */ (void) process_get_regs(KR_NEWDOM, ®s); DEBUG kdprintf(KR_OSTREAM, "Got regs\n"); /* Unless we set them otherwise, the register values are zero. The PC has already been set. We now need to initialize the stack pointer and the segment registers. */ regs.CS = DOMAIN_CODE_SEG; regs.SS = DOMAIN_DATA_SEG; regs.DS = DOMAIN_DATA_SEG; regs.ES = DOMAIN_DATA_SEG; regs.FS = DOMAIN_DATA_SEG; regs.GS = DOMAIN_DATA_SEG; regs.pc = 0; /* Place Holder!! */ regs.EFLAGS = 0x200;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -