Пример #1
0
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);
}
Пример #2
0
static INLINE int
pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,  
                          pb_size size,
                          const struct pb_desc *desc)
{
   if(buf->base.size < size)
      return 0;

   /* be lenient with size */
   if(buf->base.size >= 2*size)
      return 0;
   
   if(!pb_check_alignment(desc->alignment, buf->base.alignment))
      return 0;
   
   if(!pb_check_usage(desc->usage, buf->base.usage))
      return 0;

   if (buf->mgr->provider->is_buffer_busy) {
      if (buf->mgr->provider->is_buffer_busy(buf->mgr->provider, buf->buffer))
         return -1;
   } else {
      void *ptr = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL);

      if (!ptr)
         return -1;

      pb_unmap(buf->buffer);
   }

   return 1;
}
Пример #3
0
static struct pb_buffer *
pb_cache_manager_create_buffer(struct pb_manager *_mgr, 
                               pb_size size,
                               const struct pb_desc *desc)
{
   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
   struct pb_cache_buffer *buf;

   /* get a buffer from the cache */
   buf = (struct pb_cache_buffer *)
         pb_cache_reclaim_buffer(&mgr->cache, size, desc->alignment,
                                 desc->usage, 0);
   if (buf)
      return &buf->base;

   /* create a new one */
   buf = CALLOC_STRUCT(pb_cache_buffer);
   if (!buf)
      return NULL;
   
   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);

   /* Empty the cache and try again. */
   if (!buf->buffer) {
      pb_cache_release_all_buffers(&mgr->cache);
      buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
   }

   if(!buf->buffer) {
      FREE(buf);
      return NULL;
   }
   
   assert(pipe_is_referenced(&buf->buffer->reference));
   assert(pb_check_alignment(desc->alignment, buf->buffer->alignment));
   assert(buf->buffer->size >= size);
   
   pipe_reference_init(&buf->base.reference, 1);
   buf->base.alignment = buf->buffer->alignment;
   buf->base.usage = buf->buffer->usage;
   buf->base.size = buf->buffer->size;
   
   buf->base.vtbl = &pb_cache_buffer_vtbl;
   buf->mgr = mgr;
   pb_cache_init_entry(&mgr->cache, &buf->cache_entry, &buf->base, 0);
   
   return &buf->base;
}
Пример #4
0
static struct pb_buffer *
pb_debug_manager_create_buffer(struct pb_manager *_mgr, 
                               size_t size,
                               const struct pb_desc *desc)
{
   struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
   struct pb_debug_buffer *buf;
   struct pb_desc real_desc;
   size_t real_size;
   
   buf = CALLOC_STRUCT(pb_debug_buffer);
   if(!buf)
      return NULL;
   
   real_size = size + 2*mgr->band_size;
   real_desc = *desc;
   real_desc.usage |= PIPE_BUFFER_USAGE_CPU_WRITE;
   real_desc.usage |= PIPE_BUFFER_USAGE_CPU_READ;

   buf->buffer = mgr->provider->create_buffer(mgr->provider, 
                                              real_size, 
                                              &real_desc);
   if(!buf->buffer) {
      FREE(buf);
      return NULL;
   }
   
   assert(buf->buffer->base.refcount >= 1);
   assert(pb_check_alignment(real_desc.alignment, buf->buffer->base.alignment));
   assert(pb_check_usage(real_desc.usage, buf->buffer->base.usage));
   assert(buf->buffer->base.size >= real_size);
   
   buf->base.base.refcount = 1;
   buf->base.base.alignment = desc->alignment;
   buf->base.base.usage = desc->usage;
   buf->base.base.size = size;
   
   buf->base.vtbl = &pb_debug_buffer_vtbl;
   buf->mgr = mgr;

   buf->underflow_size = mgr->band_size;
   buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size;
   
   pb_debug_buffer_fill(buf);
   
   return &buf->base;
}
Пример #5
0
static INLINE boolean
pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,  
                          pb_size size,
                          const struct pb_desc *desc)
{
   if(buf->base.base.size < size)
      return FALSE;

   /* be lenient with size */
   if(buf->base.base.size >= 2*size)
      return FALSE;
   
   if(!pb_check_alignment(desc->alignment, buf->base.base.alignment))
      return FALSE;
   
   if(!pb_check_usage(desc->usage, buf->base.base.usage))
      return FALSE;
   
   return TRUE;
}
Пример #6
0
/**
 * \return 1   if compatible and can be reclaimed
 *         0   if incompatible
 *        -1   if compatible and can't be reclaimed
 */
static int
pb_cache_is_buffer_compat(struct pb_cache_entry *entry,
                          pb_size size, unsigned alignment, unsigned usage)
{
   struct pb_cache *mgr = entry->mgr;
   struct pb_buffer *buf = entry->buffer;

   if (!pb_check_usage(usage, buf->usage))
      return 0;

   /* be lenient with size */
   if (buf->size < size ||
       buf->size > (unsigned) (mgr->size_factor * size))
      return 0;

   if (usage & mgr->bypass_usage)
      return 0;

   if (!pb_check_alignment(alignment, buf->alignment))
      return 0;

   return mgr->can_reclaim(buf) ? 1 : -1;
}
Пример #7
0
static struct pb_buffer *
pb_debug_manager_create_buffer(struct pb_manager *_mgr, 
                               pb_size size,
                               const struct pb_desc *desc)
{
   struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
   struct pb_debug_buffer *buf;
   struct pb_desc real_desc;
   pb_size real_size;
   
   assert(size);
   assert(desc->alignment);

   buf = CALLOC_STRUCT(pb_debug_buffer);
   if(!buf)
      return NULL;
   
   real_size = mgr->underflow_size + size + mgr->overflow_size;
   real_desc = *desc;
   real_desc.usage |= PIPE_BUFFER_USAGE_CPU_WRITE;
   real_desc.usage |= PIPE_BUFFER_USAGE_CPU_READ;

   buf->buffer = mgr->provider->create_buffer(mgr->provider, 
                                              real_size, 
                                              &real_desc);
   if(!buf->buffer) {
      FREE(buf);
#if 0
      pipe_mutex_lock(mgr->mutex);
      debug_printf("%s: failed to create buffer\n", __FUNCTION__);
      if(!LIST_IS_EMPTY(&mgr->list))
         pb_debug_manager_dump(mgr);
      pipe_mutex_unlock(mgr->mutex);
#endif
      return NULL;
   }
   
   assert(pipe_is_referenced(&buf->buffer->base.reference));
   assert(pb_check_alignment(real_desc.alignment, buf->buffer->base.alignment));
   assert(pb_check_usage(real_desc.usage, buf->buffer->base.usage));
   assert(buf->buffer->base.size >= real_size);
   
   pipe_reference_init(&buf->base.base.reference, 1);
   buf->base.base.alignment = desc->alignment;
   buf->base.base.usage = desc->usage;
   buf->base.base.size = size;
   
   buf->base.vtbl = &pb_debug_buffer_vtbl;
   buf->mgr = mgr;

   buf->underflow_size = mgr->underflow_size;
   buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size;
   
   debug_backtrace_capture(buf->create_backtrace, 1, PB_DEBUG_CREATE_BACKTRACE);

   pb_debug_buffer_fill(buf);
   
   pipe_mutex_init(buf->mutex);
   
   pipe_mutex_lock(mgr->mutex);
   LIST_ADDTAIL(&buf->head, &mgr->list);
   pipe_mutex_unlock(mgr->mutex);

   return &buf->base;
}
Пример #8
0
static struct pb_buffer *
pb_cache_manager_create_buffer(struct pb_manager *_mgr, 
                               pb_size size,
                               const struct pb_desc *desc)
{
   struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
   struct pb_cache_buffer *buf;
   struct pb_cache_buffer *curr_buf;
   struct list_head *curr, *next;
   int64_t now;
   
   pipe_mutex_lock(mgr->mutex);

   buf = NULL;
   curr = mgr->delayed.next;
   next = curr->next;
   
   /* search in the expired buffers, freeing them in the process */
   now = os_time_get();
   while(curr != &mgr->delayed) {
      curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
      if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
	 buf = curr_buf;
      else if(os_time_timeout(curr_buf->start, curr_buf->end, now))
	 _pb_cache_buffer_destroy(curr_buf);
      else
         /* This buffer (and all hereafter) are still hot in cache */
         break;
      curr = next; 
      next = curr->next;
   }

   /* keep searching in the hot buffers */
   if(!buf) {
      while(curr != &mgr->delayed) {
         curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
         if(pb_cache_is_buffer_compat(curr_buf, size, desc)) {
            buf = curr_buf;
            break;
         }
         /* no need to check the timeout here */
         curr = next;
         next = curr->next;
      }
   }
   
   if(buf) {
      LIST_DEL(&buf->head);
      pipe_mutex_unlock(mgr->mutex);
      /* Increase refcount */
      pipe_reference_init(&buf->base.base.reference, 1);
      return &buf->base;
   }
   
   pipe_mutex_unlock(mgr->mutex);

   buf = CALLOC_STRUCT(pb_cache_buffer);
   if(!buf)
      return NULL;
   
   buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
   if(!buf->buffer) {
      FREE(buf);
      return NULL;
   }
   
   assert(pipe_is_referenced(&buf->buffer->base.reference));
   assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
   assert(pb_check_usage(desc->usage, buf->buffer->base.usage));
   assert(buf->buffer->base.size >= size);
   
   pipe_reference_init(&buf->base.base.reference, 1);
   buf->base.base.alignment = buf->buffer->base.alignment;
   buf->base.base.usage = buf->buffer->base.usage;
   buf->base.base.size = buf->buffer->base.size;
   
   buf->base.vtbl = &pb_cache_buffer_vtbl;
   buf->mgr = mgr;
   
   return &buf->base;
}