Пример #1
0
/**
 * 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;
}
Пример #2
0
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;
}