/** * Allocates items on the kernel's heap. * @param amount the amount of memory to allocate. * @return a pointer to the memory allocated, or nullptr if no memory was allocated. */ extern "C" addr_t kmalloc(size_t amount) { if(!kmalloc_ready) panic("kmalloc: the heap has not been initialized for utilization by kmalloc"); size_t blocks = (amount / KHeapNode::Granularity) + 1; // Find the first fit auto heap_ptr = heap_info_start_ptr; for(; heap_ptr && !(heap_ptr->size >= blocks && !heap_ptr->used); heap_ptr = heap_ptr->next); // There were no spaces large enough to allocate our heap if(heap_ptr == nullptr) panic("kmalloc: no memory available to allocate"); if(blocks < heap_ptr->size) { auto old_next = heap_ptr->next; auto new_next = alloc_kern_heapnode(); if(new_next == nullptr) panic("kmalloc: could not allocate heap node"); heap_ptr->next = new_next; new_next->next = old_next; new_next->used = false; new_next->size = heap_ptr->size - blocks; new_next->start = AS_ADDR(AS_U32(heap_ptr->start) + (blocks * KHeapNode::Granularity)); } heap_ptr->size = blocks; heap_ptr->used = true; return heap_ptr->start; }
static void unwind_kernel_handler (frame_state_t * fs) { PDSCDEF * pv = PV_FOR (fs->fp); CHFDEF1 *sigargs; CHFDEF2 *mechargs; /* Retrieve the arguments passed to the handler, by way of a VMS service providing the corresponding "Invocation Context Block". */ { long handler_ivhandle; INVO_CONTEXT_BLK handler_ivcb; CHFCTX *chfctx; handler_ivcb.libicb$q_ireg [29] = AS_REG (fs->fp); handler_ivcb.libicb$q_ireg [30] = 0; handler_ivhandle = LIB$GET_INVO_HANDLE (&handler_ivcb); if ((LIB$GET_INVO_CONTEXT (handler_ivhandle, &handler_ivcb) & 1) != 1) return; chfctx = (CHFCTX *) AS_ADDR (handler_ivcb.libicb$ph_chfctx_addr); sigargs = (CHFDEF1 *) AS_ADDR (chfctx->chfctx$q_sigarglst); mechargs = (CHFDEF2 *) AS_ADDR (chfctx->chfctx$q_mcharglst); } /* Compute the saved return address as the PC of the instruction causing the condition, accounting for the fact that it will be adjusted by the next call to "unwind" as if it was an actual call return address. */ { /* ABI-6.5.1.1 [Signal Argument Vector]: The signal occurrence address is available from the sigargs argument to the handler, designed to support both 32 and 64 bit addresses. The initial reference we get is a pointer to the 32bit form, from which one may extract a pointer to the 64bit version if need be. We work directly from the 32bit form here. */ /* The sigargs vector structure for 32bits addresses is: <......32bit......> +-----------------+ | Vsize | :chf$is_sig_args +-----------------+ -+- | Condition Value | : [0] +-----------------+ : | ... | : +-----------------+ : vector of Vsize entries | Signal PC | : +-----------------+ : | PS | : [Vsize - 1] +-----------------+ -+- */ unsigned long * sigargs_vector = ((unsigned long *) (&sigargs->chf$is_sig_args)) + 1; long sigargs_vsize = sigargs->chf$is_sig_args; fs->saved_rar = (REG) sigargs_vector [sigargs_vsize - 2] + PC_ADJUST; } fs->saved_spr = RA_UNKNOWN; fs->saved_fpr = (REG) mechargs->chf$q_mch_frame; fs->saved_pvr = (REG) mechargs->chf$q_mch_savr27; fs->saved_regs[16] = (REG) mechargs->chf$q_mch_savr16; fs->saved_regs[17] = (REG) mechargs->chf$q_mch_savr17; fs->saved_regs[18] = (REG) mechargs->chf$q_mch_savr18; fs->saved_regs[19] = (REG) mechargs->chf$q_mch_savr19; fs->saved_regs[20] = (REG) mechargs->chf$q_mch_savr20; }