static struct pb_buffer *
mm_bufmgr_create_buffer(struct pb_manager *mgr, 
                        pb_size size,
                        const struct pb_desc *desc)
{
   struct mm_pb_manager *mm = mm_pb_manager(mgr);
   struct mm_buffer *mm_buf;

   /* We don't handle alignments larger then the one initially setup */
   assert(pb_check_alignment(desc->alignment, (pb_size)1 << mm->align2));
   if(!pb_check_alignment(desc->alignment, (pb_size)1 << mm->align2))
      return NULL;
   
   mtx_lock(&mm->mutex);

   mm_buf = CALLOC_STRUCT(mm_buffer);
   if (!mm_buf) {
      mtx_unlock(&mm->mutex);
      return NULL;
   }

   pipe_reference_init(&mm_buf->base.reference, 1);
   mm_buf->base.alignment = desc->alignment;
   mm_buf->base.usage = desc->usage;
   mm_buf->base.size = size;
   
   mm_buf->base.vtbl = &mm_buffer_vtbl;
   
   mm_buf->mgr = mm;
   
   mm_buf->block = u_mmAllocMem(mm->heap, (int)size, (int)mm->align2, 0);
   if(!mm_buf->block) {
#if 0
      debug_printf("warning: heap full\n");
      mmDumpMemInfo(mm->heap);
#endif
      FREE(mm_buf);
      mtx_unlock(&mm->mutex);
      return NULL;
   }
   
   /* Some sanity checks */
   assert(0 <= (pb_size)mm_buf->block->ofs && (pb_size)mm_buf->block->ofs < mm->size);
   assert(size <= (pb_size)mm_buf->block->size && (pb_size)mm_buf->block->ofs + (pb_size)mm_buf->block->size <= mm->size);
   
   mtx_unlock(&mm->mutex);
   return SUPER(mm_buf);
}
void *
rtasm_exec_malloc(size_t size)
{
   struct mem_block *block = NULL;
   void *addr = NULL;

   pipe_mutex_lock(exec_mutex);

   init_heap();

   if (exec_heap) {
      size = (size + 31) & ~31;  /* next multiple of 32 bytes */
      block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */
   }

   if (block)
      addr = exec_mem + block->ofs;
   else 
      debug_printf("rtasm_exec_malloc failed\n");
   
   pipe_mutex_unlock(exec_mutex);
   
   return addr;
}