void backend_unregister_dynamic(backend_t *be) { hts_lwmutex_lock(&dyanamic_backends_mutex); LIST_REMOVE(be, be_global_link); hts_lwmutex_unlock(&dyanamic_backends_mutex); }
void free(void *ptr) { if(ptr == NULL) return; const int bs = tlsf_block_size(ptr); if(bs >= 65536) { const int p = (intptr_t)ptr; const int np = ROUND_UP(p, 65536); int s = bs - (np - p); if(s > 0) { s &= ~0xffff; if(s > 0) { #if 0 tracelog(TRACE_NO_PROP, TRACE_DEBUG, "MEMORY", "free(%p+%d) == page_free(0x%x+%d)", ptr, bs, np, s); #endif #ifdef USE_VIRTUAL_MEM if(Lv2Syscall2(308, np, s)) // Invalidate tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "Invalidate failed"); if(Lv2Syscall2(310, np, s)) // Sync tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "Sync failed"); #endif } } } hts_lwmutex_lock(&mutex); tlsf_free(gpool, ptr); hts_lwmutex_unlock(&mutex); }
void backend_register_dynamic(backend_t *be) { hts_lwmutex_lock(&dyanamic_backends_mutex); LIST_INSERT_HEAD(&dynamic_backends, be, be_global_link); hts_lwmutex_unlock(&dyanamic_backends_mutex); }
void myfree(void *ptr) { if(ptr == NULL) return; hts_lwmutex_lock(&mutex); tlsf_free(gpool, ptr); hts_lwmutex_unlock(&mutex); }
struct mallinfo mallinfo(void) { struct mallinfo mi; mi.arena = total_avail; hts_lwmutex_lock(&mutex); mi.uordblks = tlsf_used(gpool); hts_lwmutex_unlock(&mutex); mi.fordblks = mi.arena - mi.uordblks; return mi; }
void verify_heap(void) { hts_lwmutex_lock(&mutex); int r = tlsf_check_heap(gpool); hts_lwmutex_unlock(&mutex); if(r) tracelog(TRACE_NO_PROP, TRACE_ERROR, "HEAPCHECK", "Heap check verify failed"); else tracelog(TRACE_NO_PROP, TRACE_DEBUG, "HEAPCHECK", "Heap OK"); }
void * myrealloc(void *ptr, size_t bytes) { hts_lwmutex_lock(&mutex); void *r = tlsf_realloc(gpool, ptr, bytes); hts_lwmutex_unlock(&mutex); if(r == NULL) { memtrace(); tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "realloc(%d) failed", (int)bytes); errno = ENOMEM; } return r; }
void *memalign(size_t align, size_t bytes) { void *r; if(bytes == 0) return NULL; hts_lwmutex_lock(&mutex); r = tlsf_memalign(gpool, align, bytes); hts_lwmutex_unlock(&mutex); if(r == NULL) { memtrace(); panic("OOM: memalign(%d, %d)", (int)align, (int)bytes); } return r; }
void *malloc(size_t bytes) { void *r; if(bytes == 0) return NULL; hts_lwmutex_lock(&mutex); r = tlsf_malloc(gpool, bytes); hts_lwmutex_unlock(&mutex); if(r == NULL) { memtrace(); panic("OOM: malloc(%d)", (int)bytes); } return r; }
void *mymemalign(size_t align, size_t bytes) { if(bytes == 0) return NULL; hts_lwmutex_lock(&mutex); void *r = tlsf_memalign(gpool, align, bytes); hts_lwmutex_unlock(&mutex); if(r == NULL) { memtrace(); tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "memalign(%d,%d) failed", (int)align, (int)bytes); errno = ENOMEM; } return r; }
void *realloc(void *ptr, size_t bytes) { void *r; if(bytes == 0) { free(ptr); return NULL; } hts_lwmutex_lock(&mutex); r = tlsf_realloc(gpool, ptr, bytes); hts_lwmutex_unlock(&mutex); if(r == NULL) { memtrace(); panic("OOM: realloc(%p, %d)", ptr, (int)bytes); } return r; }
static void memtrace(void) { memstats_t ms = {0}; hts_lwmutex_lock(&mutex); tlsf_walk_heap(gpool, mywalker, &ms); hts_lwmutex_unlock(&mutex); tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "Memory allocator status -- Used: %d (%d segs) Free: %d (%d segs)", ms.used, ms.used_segs, ms.free, ms.free_segs); for(int i = 0; i < 33; i++) { tracelog(TRACE_NO_PROP, TRACE_ERROR, "MEMORY", "%2d: %8d %8d", i, ms.hist_used[i], ms.hist_free[i]); } }
static int memstats(http_connection_t *hc, const char *remain, void *opaque, http_cmd_t method) { htsbuf_queue_t out; allsegs_t as = {}; hts_lwmutex_lock(&mutex); tlsf_walk_heap(gpool, list_all_segs_walk, &as); int size = as.count * sizeof(seginfo_t); as.ptr = halloc(size); as.count = 0; tlsf_walk_heap(gpool, list_all_segs_walk, &as); hts_lwmutex_unlock(&mutex); qsort(as.ptr, as.count, sizeof(seginfo_t), seginfo_cmp); htsbuf_queue_init(&out, 0); htsbuf_qprintf(&out, "%d segments ptr=%p\n\n", as.count, as.ptr); int lastsize = -1; int dup = 0; for(int i = 0; i < as.count; i++) { if(as.ptr[i].size == lastsize && i != as.count - 1) { dup++; } else { htsbuf_qprintf(&out, "%s %10d * %d\n", as.ptr[i].used ? "Used" : "Free", as.ptr[i].size, dup + 1); dup = 0; } lastsize = as.ptr[i].size; } hfree(as.ptr, size); return http_send_reply(hc, 0, "text/plain", NULL, NULL, 0, &out); }
static int video_ps3_vdec_codec_create(media_codec_t *mc, const media_codec_params_t *mcp, media_pipe_t *mp) { vdec_decoder_t *vdd; struct vdec_type dec_type = {0}; struct vdec_attr dec_attr = {0}; int spu_threads; int r; int crop_right = 0; int crop_bottom = 0; switch(mc->codec_id) { case AV_CODEC_ID_MPEG2VIDEO: hts_lwmutex_lock(&ps3_codec_sysmodule_mutex); if(vdec_mpeg2_loaded == -1) vdec_mpeg2_loaded = !SysLoadModule(SYSMODULE_VDEC_MPEG2); if(!vdec_mpeg2_loaded) { hts_lwmutex_unlock(&ps3_codec_sysmodule_mutex); return no_lib(mp, "MPEG-2"); } hts_lwmutex_unlock(&ps3_codec_sysmodule_mutex); dec_type.codec_type = VDEC_CODEC_TYPE_MPEG2; dec_type.profile_level = VDEC_MPEG2_MP_HL; spu_threads = 1; break; case AV_CODEC_ID_H264: if(mcp != NULL) { TRACE(TRACE_DEBUG, "VDEC", "H264: Profile:%d Level:%d", mcp->profile, mcp->level); if(mcp->profile != FF_PROFILE_H264_CONSTRAINED_BASELINE && mcp->profile >= FF_PROFILE_H264_HIGH_10) { TRACE(TRACE_DEBUG, "VDEC", "Refusing to play h264 profile %d", mcp->profile); return 1; // No 10bit support } if(mcp->extradata != NULL) { h264_parser_t hp; hexdump("extradata", mcp->extradata, mcp->extradata_size); if(h264_parser_init(&hp, mcp->extradata, mcp->extradata_size)) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: Broken headers, Disabling acceleration")); return -1; } TRACE(TRACE_DEBUG, "VDEC", "Dumping SPS"); int too_big_refframes = 0; int mb_height = 0; for(int i = 0; i < H264_PARSER_NUM_SPS; i++) { const h264_sps_t *s = &hp.sps_array[i]; if(!s->present) continue; TRACE(TRACE_DEBUG, "VDEC", "SPS[%d]: %d x %d profile:%d level:%d.%d ref-frames:%d", i, s->mb_width * 16, s->mb_height * 16, s->profile, s->level / 10, s->level % 10, s->num_ref_frames); TRACE(TRACE_DEBUG, "VDEC", " crop: left:%d right:%d top:%d bottom:%d", s->crop_left, s->crop_right, s->crop_top, s->crop_bottom); crop_right = s->crop_right; crop_bottom = s->crop_bottom; if(s->mb_height >= 45 && s->num_ref_frames > 9) too_big_refframes = s->num_ref_frames; if(s->mb_height >= 68 && s->num_ref_frames > 4) too_big_refframes = s->num_ref_frames; mb_height = s->mb_height; } h264_parser_fini(&hp); if(too_big_refframes) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Cell-h264: %d Ref-frames for %d content is incompatible with PS3 HW decoder. Disabling acceleration"), too_big_refframes, mb_height * 16); return -1; } } } hts_lwmutex_lock(&ps3_codec_sysmodule_mutex); if(vdec_h264_loaded == -1) vdec_h264_loaded = !SysLoadModule(SYSMODULE_VDEC_H264); if(!vdec_h264_loaded) { hts_lwmutex_unlock(&ps3_codec_sysmodule_mutex); return no_lib(mp, "h264"); } hts_lwmutex_unlock(&ps3_codec_sysmodule_mutex); dec_type.codec_type = VDEC_CODEC_TYPE_H264; if(mcp != NULL && mcp->level > 42) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 5, _("Cell-h264: Forcing level 4.2 for content in level %d.%d. This may break video playback."), mcp->level / 10, mcp->level % 10); } dec_type.profile_level = 42; spu_threads = 4; break; default: return 1; } r = vdec_query_attr(&dec_type, &dec_attr); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to query Cell codec. Error 0x%x"), r); return 1; } vdd = calloc(1, sizeof(vdec_decoder_t)); #define ROUND_UP(p, round) ((p + round - 1) & ~(round - 1)) size_t allocsize = ROUND_UP(dec_attr.mem_size, 1024*1024); u32 taddr; if(Lv2Syscall3(348, allocsize, 0x400, (u64)&taddr)) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Unable to allocate %d bytes of RAM"), dec_attr.mem_size); return 1; } vdd->mem = (void *)(uint64_t)taddr; TRACE(TRACE_DEBUG, "VDEC", "Opening codec %s level %d using %d bytes of RAM", mc->codec_id == AV_CODEC_ID_H264 ? "h264" : "MPEG2", dec_type.profile_level, dec_attr.mem_size); vdd->config.mem_addr = (intptr_t)vdd->mem; vdd->config.mem_size = dec_attr.mem_size; vdd->config.num_spus = spu_threads; vdd->config.ppu_thread_prio = THREAD_PRIO_VDEC; vdd->config.spu_thread_prio = VDEC_SPU_PRIO; vdd->config.ppu_thread_stack_size = 1 << 14; vdec_closure c; c.fn = (intptr_t)OPD32(decoder_callback); c.arg = (intptr_t)vdd; r = vdec_open(&dec_type, &vdd->config, &c, &vdd->handle); if(r) { notify_add(mp->mp_prop_notifications, NOTIFY_WARNING, NULL, 10, _("Unable to open Cell codec. Error 0x%x"), r); Lv2Syscall1(349, (uint64_t)vdd->mem); free(vdd); return 1; } if(mcp != NULL) { vdd->level_major = mcp->level / 10; vdd->level_minor = mcp->level % 10; vdd->filter_aud = mcp->broken_aud_placement; } if(mc->codec_id == AV_CODEC_ID_H264 && mcp != NULL && mcp->extradata_size) h264_to_annexb_init(&vdd->annexb, mcp->extradata, mcp->extradata_size); vdd->max_order = -1; hts_mutex_init(&vdd->mtx); hts_cond_init(&vdd->audone, &vdd->mtx); hts_cond_init(&vdd->seqdone, &vdd->mtx); TRACE(TRACE_DEBUG, "VDEC", "Cell accelerated codec created using %d bytes of RAM", dec_attr.mem_size); mc->opaque = vdd; mc->decode = decoder_decode; mc->flush = decoder_flush; mc->close = decoder_close; vdd->crop_right = crop_right; vdd->crop_bottom = crop_bottom; vdec_start_sequence(vdd->handle); return 0; }