Beispiel #1
0
void rs_release_resources()
{
    gfx_delayed_release();

    /* wait for load task to finish */
    if (g_rs.load_jobid != 0)   {
        tsk_wait(g_rs.load_jobid);
        tsk_destroy(g_rs.load_jobid);
    }

    /* unload everything in queued loads */
    for (uint i = 0; i < g_rs.job_params.cnt; i++)    {
        reshandle_t hdl = g_rs.job_params.load_items[i]->hdl;
        void* ptr = g_rs.job_result.ptrs[i];
        if (ptr != NULL)    {
            struct rs_resource* r = rs_resource_get(hdl);
            r->unload_func(ptr);
        }
    }

    if (g_rs.blank_tex != NULL) {
        gfx_destroy_texture(g_rs.blank_tex);
        g_rs.blank_tex = NULL;
    }
}
Beispiel #2
0
/* Invoked when swap has been freed for the task */
INT32 cmd_swap_freed_callback(struct fsio_event_source *iosrc, INT32 ioret) 
{
	struct pm_msg_finished pm_finished;
	struct pm_task *task = tsk_get(iosrc->id);
    
	// if there is a destroy sender, send an ok to the task
	if( task->command_inf.command_sender_id != 0)
	{
		struct pm_msg_response msg_ans;
			
		msg_ans.pm_type = PM_DESTROY_TASK;
		msg_ans.req_id  = task->command_inf.command_req_id;
		msg_ans.status  = PM_OK;
		msg_ans.new_id  = task->id;
		msg_ans.new_id_aux = -1;
			
		send_msg(task->command_inf.command_sender_id, task->command_inf.command_ret_port, &msg_ans);
	}

	if(task->creator_task != 0xFFFF)
	{
		// inform the creating task 
		pm_finished.pm_type = PM_TASK_FINISHED;
		pm_finished.req_id =  0;
		pm_finished.taskid = task->id;
		pm_finished.ret_value = task->command_inf.ret_value;

		send_msg(task->creator_task, task->creator_task_port, &pm_finished);
	}    

    if(task->dbg_task != 0xFFFF)
	{
        struct dbg_message dbg_msg;
		// inform the creating task 
		dbg_msg.command = DEBUG_TASK_FINISHED;
		dbg_msg.task = task->id;
		
		send_msg(task->dbg_task, task->dbg_port, &dbg_msg);
	}

	task->command_inf.command_sender_id = 0xFFFF;
    task->creator_task = 0xFFFF;
    task->dbg_task = 0xFFFF;
	
	if(shuttingDown())
		shutdown_tsk_unloaded(task->id);
	
    if(!tsk_destroy(task))
		pman_print("PMAN: Could not destroy task");

	return 1;
}
Beispiel #3
0
/* Runs in main thread, syncs resources */
void rs_update()
{
    uint job_id = g_rs.load_jobid;
    if (job_id != 0)    {
        if (!tsk_check_finished(job_id))    {
            gfx_delayed_createobjects();
            return;
        }   else    {
            gfx_delayed_finalizeobjects();
        }
    }

    struct rs_load_job_params* params = &g_rs.job_params;
    struct rs_load_job_result* result = &g_rs.job_result;

    /* if we already have a job_id, it means that the job is finished
     * update the database and destroy the task */
    if (job_id != 0)    {
        struct rs_load_job_params* params = (struct rs_load_job_params*)tsk_get_params(job_id);
        struct rs_load_job_result* result = (struct rs_load_job_result*)tsk_get_result(job_id);

        for (uint i = 0; i < params->cnt; i++)    {
            struct rs_load_data* ldata = params->load_items[i];
            reshandle_t hdl = ldata->hdl;

            /* check the handle in unload list and unload immediately */
            int must_unload = rs_search_in_unloads(hdl);

            struct rs_resource* r = rs_resource_get(hdl);
            if (result->ptrs[i] != NULL)    {
                r->ptr = result->ptrs[i];

                if (!must_unload)    {
                    /* register hot-loading */
                    if (BIT_CHECK(g_rs.flags, RS_FLAG_HOTLOADING) && !ldata->reload)
                        rs_register_hotload(ldata);

                    /* apply reload funcs */
                    rs_resource_manualreload(ldata);
                }   else    {
                    rs_remove_fromdb(hdl);
                }
            }   else if (must_unload)   {
                rs_remove_fromdb(hdl);
            }

            mem_pool_free(&g_rs.load_data_pool, params->load_items[i]);
        }

        /* cleanup */
        tsk_destroy(job_id);
    }

    /* fill new params and dispatch the job */
    struct linked_list* lnode = g_rs.load_list;
    uint qcnt = 0;
    while (qcnt < g_rs.load_threads_max && lnode != NULL)    {
        params->load_items[qcnt++] = (struct rs_load_data*)lnode->data;
        list_remove(&g_rs.load_list, lnode);
        lnode = g_rs.load_list;
    }
    params->cnt = qcnt;

    /* dispatch to first thread only (exclusive mode) */
    if (qcnt > 0)   {
        int thread_cnt = (int)g_rs.load_threads_max;
        struct allocator* tmp_alloc = tsk_get_tmpalloc(0);
        int* thread_idxs = (int*)A_ALLOC(tmp_alloc, sizeof(uint)*thread_cnt, MID_RES);
        ASSERT(thread_idxs);
        for (int i = 0; i < thread_cnt; i++)
            thread_idxs[i] = i;
        g_rs.load_jobid = tsk_dispatch_exclusive(rs_threaded_load_fn, thread_idxs, thread_cnt,
            params, result);
        A_FREE(tmp_alloc, thread_idxs);
    }   else    {
        g_rs.load_jobid = 0;
    }
}
Beispiel #4
0
INT32 elf_fileclosed_callback(struct fsio_event_source *iosrc, INT32 ioret)
{
    // file was closed because of an error, destroy the task
    tsk_destroy(tsk_get(iosrc->id));
}
Beispiel #5
0
void cmd_create_task(struct pm_msg_create_task *msg, struct pm_task *ctask) 
{
	struct pm_task *tsk = NULL;
	UINT16 new_task_id = msg->new_task_id;
	UINT16 flags = msg->flags;
	UINT16 type = (flags & SERVER_TASK) / SERVER_TASK;
	UINT32 psize, ret;
	char *path = NULL;

	if(pman_stage == PMAN_STAGE_INITIALIZING)
	{
		cmd_inform_result(msg, ctask->id, PM_IS_INITIALIZING, 0, 0);
		return;
	}

	if(new_task_id != 0xFFFF) 
	{
		if (tsk_lower_bound[type] <=  new_task_id && new_task_id <=  tsk_upper_bound[type]) 
		{
			tsk = tsk_get(new_task_id);

			if(tsk != NULL) 
			{
				/* new_task_id is not free to be used */
				cmd_inform_result(msg, ctask->id, PM_TASK_ID_TAKEN, 0, 0);
				return;
			}
	    } 
		else 
		{
			/* new_task_id is out of range */
			cmd_inform_result(msg, ctask->id, PM_TASK_ID_INVALID, 0, 0);
			return;
		}
	}
	else 
	{
		/* search for a free task id */
		new_task_id = tsk_get_id(tsk_lower_bound[type], tsk_upper_bound[type]);
    
		if(new_task_id == 0xFFFF) 
		{
			cmd_inform_result(msg, ctask->id, PM_NO_FREE_ID, 0, 0);
			return;
        }
	}
  
	tsk = tsk_create(new_task_id);
    if(tsk == NULL)
    {
        cmd_inform_result(msg, ctask->id, PM_NOT_ENOUGH_MEM, 0, 0);
        return;
    }
	path = NULL;
	psize = mem_size(msg->path_smo_id);

	if(psize < 1)
	{
        tsk_destroy(tsk);
		cmd_inform_result(msg, ctask->id, PM_BAD_SMO, 0, 0);
		return;
	}

	path = kmalloc(psize);

	if(path == NULL)
	{
        tsk_destroy(tsk);
		cmd_inform_result(msg, ctask->id, PM_NOT_ENOUGH_MEM, 0, 0);
		return;
	}
	
	/* Read Path */
	if(read_mem(msg->path_smo_id, 0, psize, path) != SUCCESS) 
	{
        tsk_destroy(tsk);
		cmd_inform_result(msg, ctask->id, PM_BAD_SMO, 0, 0);
		return;
	}

	tsk->flags = (flags & SERVER_TASK)? TSK_FLAG_SERVICE : 0;

	if(path[psize-1] == '\0') psize--;
    
    tsk->creator_task = ctask->id;
	tsk->creator_task_port = msg->response_port;
	tsk->command_inf.command_req_id = msg->req_id;

	tsk->command_inf.command_ret_port = -1;
	tsk->command_inf.command_sender_id = -1;

	ret = loader_create_task(tsk, path, psize, msg->param, type, LOADER_CTASK_TYPE_PRG);

	if(ret != PM_OK)
	{
        tsk_destroy(tsk);
		kfree(path);
		cmd_inform_result(msg, ctask->id, ret, 0, 0);
	}
}
Beispiel #6
0
/*
Unload the specified lib. 
*/
BOOL vmm_lib_unload(struct pm_task *task, struct vmm_memory_region *mreg)
{
    struct vmm_slib_descriptor *lib = (struct vmm_slib_descriptor*)mreg->descriptor;
 
    if(lib == NULL)
    {
        ma_remove(&task->vmm_info.regions, &mreg->tsk_node);
        rb_remove(&task->vmm_info.regions_id, &mreg->tsk_id_node);
        kfree(mreg);
        pman_print_dbg("PMAN vmm_lib_unload: Lib is LD\n");
        return TRUE;    // this can only happen on the LD mapping
    }

    pman_print_dbg("PMAN vmm_lib_unload: Claim memory from task.\n");

    // claim memory from the referencing task
    vmm_claim_region(task, mreg);

    ma_remove(&task->vmm_info.regions, &mreg->tsk_node);
    rb_remove(&task->vmm_info.regions_id, &mreg->tsk_id_node);
    
    // fix regions list on the descriptor
    if(mreg->prev == NULL)
        lib->regions = mreg->next;
    else
        mreg->prev->next = mreg->next;
    if(mreg->next)
        mreg->next->prev = mreg->prev;

    kfree(mreg);

    lib->references--;

    pman_print_dbg("PMAN vmm_lib_unload: Lib references %i\n", lib->references);

    if(!lib->references && lib->loaded)
    {
        struct pm_task *ltask = tsk_get(lib->task);

        pman_print_dbg("PMAN vmm_lib_unload: Lib UNLOADING\n");

		/* Close the file but dont wait for a callback */
        struct stdfss_close msg_close;

	    msg_close.command  = STDFSS_CLOSE;
	    msg_close.thr_id   = -1;
	    msg_close.file_id  = ltask->io_event_src.file_id;
	    msg_close.ret_port = 50; // this port is clearly not open

	    send_msg(ltask->io_event_src.fs_service, STDFSS_PORT, &msg_close);

        // destroy the task
        tsk_destroy(ltask); // this should also free the path!

        // remove it from the loaded list
        if(lib->prev == NULL)
        {
            vmm.slibs = lib->next;
            vmm.slibs->prev = NULL;
        }
        else
        {
            lib->prev->next = lib->next;
        }
        if(lib->next != NULL)
            lib->next->prev = lib->prev;

        kfree(lib);

        pman_print_dbg("PMAN vmm_lib_unload: Lib FREED\n");
    }

    return TRUE;
}
Beispiel #7
0
int vmm_lib_load(struct pm_task *task, char *path, int plength, UINT32 vlow, UINT32 vhigh)
{
    struct vmm_slib_descriptor *lib = (struct vmm_slib_descriptor*)vmm_lib_get(path);
    struct vmm_memory_region *mreg = NULL;
    UINT16 libtask;
    int ret;
	struct pm_task *libtsk = NULL;

    pman_print_dbg("PM: vmm_lib_load %s l: %x h: %x\n", path, vlow, vhigh);

    vlow = TRANSLATE_ADDR(vlow,UINT32);
    vhigh = TRANSLATE_ADDR(vhigh,UINT32);

    if(ma_collition(&task->vmm_info.regions, vlow, vhigh))
        return FALSE;
        
    pman_print_dbg("PM: vmm_lib_load no collition\n");

    mreg = kmalloc(sizeof(struct vmm_memory_region));

    if(!mreg) return 0;

    if(!rb_free_value(&task->vmm_info.regions_id, &mreg->tsk_id_node.value))
	{
		kfree(mreg);
		return FALSE;
	}

    pman_print_dbg("PM: vmm_lib_load id %i\n", &mreg->tsk_id_node.value);

    if(!lib)
    {
        pman_print_dbg("PM: vmm_lib_load loading lib for the first time\n");

        lib = kmalloc(sizeof(struct vmm_slib_descriptor));

        if(!lib) 
        {
            kfree(mreg);
            return 0;
        }

        /* search for a free task id */
	    libtask = tsk_get_id(tsk_lower_bound[1], tsk_upper_bound[1]);
    
	    if(libtask == 0xFFFF) 
	    {
		    kfree(mreg);
            return 0;
        }
  
	    libtsk = tsk_create(libtask);
        if(libtsk == NULL)
        {
            kfree(mreg);
            return 0;
        }
	
        pman_print_dbg("PM: vmm_lib_load task created %i\n", libtask);

	    libtsk->flags = TSK_SHARED_LIB;
        libtsk->state = TSK_NORMAL;

	    if(path[plength-1] == '\0') plength--;
        	            
        lib->path = path;
        lib->references = 1;
        lib->regions = NULL;
        lib->task = libtask;
        lib->loaded = 0;

        // add it to the global loaded libs list
        if(vmm.slibs)
            vmm.slibs->prev = lib;
        lib->next = vmm.slibs;
        lib->prev = NULL;
        vmm.slibs = lib;

        mreg->owner_task = task->id;
        mreg->next = mreg->prev = NULL;
	    mreg->tsk_node.high = vhigh;
	    mreg->tsk_node.low = vlow;
	    mreg->flags = VMM_MEM_REGION_FLAG_NONE;
	    mreg->type = VMM_MEMREGION_LIB;
        mreg->descriptor = lib;

        lib->regions = mreg;

        pman_print_dbg("PM: vmm_lib_load invoke loader reg: %x\n", mreg);
   
	    ret = loader_create_task(libtsk, path, plength, (unsigned int)lib, 1, LOADER_CTASK_TYPE_LIB);

	    if(ret != PM_OK)
	    {
            tsk_destroy(libtsk);
		    kfree(mreg);
            return 0;
	    }
        
        pman_print_dbg("PM: vmm_lib_load loader create task ret OK\n");
        return 1;
    }

    pman_print_dbg("PM: vmm_lib_load lib is already loaded! ref: %i \n", lib->references);
    
    lib->references++;

    // complete the memory region for this task
    mreg->owner_task = task->id;
    mreg->tsk_node.high = vhigh;
	mreg->tsk_node.low = vlow;
	mreg->flags = VMM_MEM_REGION_FLAG_NONE;
	mreg->type = VMM_MEMREGION_LIB;
    mreg->descriptor = lib;

    lib->regions->next = mreg;
    mreg->prev = lib->regions;
    mreg->next = NULL;
	
    if(!lib->loaded)
    {
        pman_print_dbg("PM: vmm_lib_load lib is not loaded yet\n");
        return 1;
    }
    else
    {
        pman_print_dbg("PM: vmm_lib_load lib is loaded!\n");
         /* Add new_mreg on the task lists */
        ma_insert(&task->vmm_info.regions, &mreg->tsk_node);
        rb_search(&task->vmm_info.regions_id, mreg->tsk_id_node.value);
    }

    return 2;
}