示例#1
0
文件: pthread.c 项目: kstraube/hysim
/* Responible for creating the uthread and initializing its user trap frame */
struct uthread *pth_thread_create(void (*func)(void), void *udata)
{
	struct pthread_tcb *pthread;
	pthread_attr_t *attr = (pthread_attr_t*)udata;
	pthread = (pthread_t)calloc(1, sizeof(struct pthread_tcb));
	assert(pthread);
	pthread->stacksize = PTHREAD_STACK_SIZE;	/* default */
	pthread->id = get_next_pid();
	pthread->detached = FALSE;				/* default */
	/* Respect the attributes */
	if (attr) {
		if (attr->stacksize)					/* don't set a 0 stacksize */
			pthread->stacksize = attr->stacksize;
		if (attr->detachstate == PTHREAD_CREATE_DETACHED)
			pthread->detached = TRUE;
	}
	/* allocate a stack */
	if (__pthread_allocate_stack(pthread))
		printf("We're f****d\n");
	/* Set the u_tf to start up in __pthread_run, which will call the real
	 * start_routine and pass it the arg.  Note those aren't set until later in
	 * pthread_create(). */
	init_user_tf(&pthread->uthread.utf, (uint32_t)__pthread_run, 
                 (uint32_t)(pthread->stacktop));
	return (struct uthread*)pthread;
}
示例#2
0
文件: sched.c 项目: Fluray/sbunix
/**
 * Create a kernel task. It's state will be TASK_RUNNABLE and
 * the type will be TASK_KERN.
 * @start: function the task will start at, no arguments and returns void
 */
struct task_struct *ktask_create(void (*start)(void), const char *name) {
    struct task_struct *task;
    uint64_t *stack;

    stack = (uint64_t *)get_free_page(0);
    if(!stack)
        return NULL;

    task = kmalloc(sizeof(*task));
    if(!task)
        goto out_stack;

    memset(task, 0, sizeof(*task));

    task->type = TASK_KERN;
    task->state = TASK_RUNNABLE;
    /* Put the start function on the stack for switch_to  */
    task->first_switch = 1;
    task->foreground = 1; /* all kernel threads can read input */
    stack[510] = (uint64_t)start;
    task->kernel_rsp = (uint64_t)&stack[510];
    task->mm = &kernel_mm;
    kernel_mm.mm_count++;
    task->pid = get_next_pid();
    task_set_cmdline(task, name);
    strcpy(task->cwd, "/"); /* set cwd to root for ktasks */
    task->timeslice = TIMESLICE_BASE;

    task_add_new(task); /* add to run queue and task list */
    return task;

out_stack:
    free_page((uint64_t)stack);
    return NULL;
}
示例#3
0
文件: sched.c 项目: crazy2k/zafio
void sched_init() {

    // Creamos la tarea ``init``
    task_t *init = kmalloc(sizeof(task_t));

    init->prog = kmalloc(sizeof(program_t));
    init->prog->name = "init";

    init->pd = kernel_pd;

    init->kernel_stack = KERNEL_STACK_TOP;
    init->kernel_stack_limit = KERNEL_STACK_BOTTOM;

    init->waiting = FALSE;
    init->waited = FALSE;
    init->parent = NULL;

    init->ticks = 0;
    init->quantum = SCHED_QUANTUM;
    restart_quantum(init);
    
    init->pid = get_next_pid();

    // El stack de nivel 0 no interesa. Deberia sobreescribirse al cambiar de
    // tarea. Ademas, como estamos en espacio de kernel, no se deberia utilizar
    // el valor del stack de nivel 0 que esta en la TSS.
    init->kernel_stack_pointer = NULL;
    setup_tss(NULL);

    add_task(init);

    sti();

    init_task();
}
示例#4
0
文件: sched.c 项目: Fluray/sbunix
/**
 * Return a copy of the current task.
 */
struct task_struct *fork_curr_task(void) {
    struct task_struct *task;
    uint64_t *kstack, *curr_kstack;
    int i;

    kstack = (uint64_t *)get_free_page(0);
    if(!kstack)
        return NULL;

    task = kmalloc(sizeof(*task));
    if(!task)
        goto out_stack;

    /* Half the remaining timeslice (split between parent and child) */
    curr_task->timeslice >>= 1;

    memcpy(task, curr_task, sizeof(*task));     /* Exact copy of parent */

    /* deep copy the current mm */
    task->mm = mm_deep_copy();
    if(task->mm == NULL)
        goto out_task;

    /* Copy the curr_task's kstack */
    curr_kstack = (uint64_t *)ALIGN_DOWN(read_rsp(), PAGE_SIZE);
    memcpy(kstack, curr_kstack, PAGE_SIZE);
    task->kernel_rsp = (uint64_t)&kstack[510];  /* new kernel stack */
    task->pid = get_next_pid();                 /* new pid */
    task->parent = curr_task;                   /* new parent */
    task->chld = task->sib = NULL;              /* no children/siblings yet */
    task->next_task = task->prev_task = task->next_rq = NULL;

    /* Increment reference counts on any open files */
    for(i = 0; i < TASK_FILES_MAX; i++) {
        struct file *fp = task->files[i];
        if(fp) {
            fp->f_count++;
        }
    }

    /* Add this new child to the parent */
    add_child(curr_task, task);

    /* TODO: Here we steal our parent's foreground status */
    if(curr_task->pid > 2)
        curr_task->foreground = 0;/* change to 1; to let all tasks read */

    task_add_new(task); /* add to run queue and task list */

    return task;
out_task:
    kfree(task);
out_stack:
    free_page((uint64_t)kstack);
    return NULL;
}
示例#5
0
文件: sched.c 项目: crazy2k/zafio
/* Crea una nueva tarea lista para ser ejecutada.
 * - ``pd`` es la direccion virtual del directorio de paginas de la tarea;;
 */
task_t *create_task(uint32_t pd[], struct program_t *prog) {

    task_t *task = kmalloc(sizeof(task_t));

    task->prog = prog;

    task->pd = pd;

    task->waiting = FALSE;
    task->waited = FALSE;
    task->parent = NULL;

    task->ticks = 0;
    task->quantum = SCHED_QUANTUM;
    restart_quantum(task);
    
    task->pid = get_next_pid();

    // Alojamos memoria para el stack del kernel de la tarea
    task->kernel_stack = new_kernel_page();
    task->kernel_stack_limit = task->kernel_stack + PAGE_SIZE;
    task->kernel_stack_pointer = task->kernel_stack_limit;

    // Escribimos el task_state_t en la pila del kernel
    void *stack_pointer = elf_stack_bottom(prog->file);
    void *start_task_routine = START_TASK_VIRT_ADDR;
    task->kernel_stack_pointer -= sizeof(task_state_t);
    task_state_t *st = (task_state_t *)task->kernel_stack_pointer;
    // El stack pointer arranca en 2 posiciones abajo del tope. Una es para
    // la direccion de retorno a la que start_task deberia volver. La otra es
    // para el parametro de start_task, que sera justamente el punto de
    // entrada de la tarea.
    initialize_task_state(st, start_task_routine, stack_pointer - 8);

    // Direccion del task_t correspondiente a la tarea
    task->kernel_stack_pointer -= 4;
    *((void **)task->kernel_stack_pointer) = task;
    // Direccion de la rutina que inicializa la tarea
    task->kernel_stack_pointer -= 4;
    *((void **)task->kernel_stack_pointer) = initialize_task;

    // El valor de esta entrada en el stack no deberia tener ninguna
    // importancia. Es el valor que adquiere ebp al cambiar el contexto al
    // de la tarea nueva. Este registro no es usado hasta que adquiere el valor
    // que indica el task_state_t inicial de la tarea.
    task->kernel_stack_pointer -= 4;
    *((void **)task->kernel_stack_pointer) = NULL;

    return task;
}
示例#6
0
文件: process.c 项目: rtfb/bare-metal
process_t* new_process(process_entry_point_t func) {
    uint32_t user_stack_size = 0x100000; // XXX: this constant is already defined in boot.S, reuse
    process_t *p = kmalloc(sizeof(process_t));
    void *stack = kmalloc(user_stack_size);
    uint32_t *sp = (uint32_t*)(stack) + user_stack_size/4;
    p->stack_bottom = sp;
    p->pid = get_next_pid();

    void *env = NULL;
    //void *exit_fn = NULL;

    //*(--sp) = 0x00000010;             // CPSR (user mode with interrupts enabled)
    *(--sp) = (uint32_t)func;         // 'return' address (i.e. where we come in)
    *(--sp) = 0x0c0c0c0c;             // r12
    *(--sp) = 0x0b0b0b0b;             // r11
    *(--sp) = 0x0a0a0a0a;             // r10
    *(--sp) = 0x09090909;             // r9
    *(--sp) = 0x08080808;             // r8
    *(--sp) = 0x07070707;             // r7
    *(--sp) = 0x06060606;             // r6
    *(--sp) = 0x05050505;             // r5
    *(--sp) = 0x04040404;             // r4
    *(--sp) = 0x03030303;             // r3
    *(--sp) = 0x02020202;             // r2
    *(--sp) = 0x01010101;             // r1
    *(--sp) = (uint32_t)env;          // r0, i.e. arg to entry function

    /*
    if ((uint32_t)sp & 0x07) {
        *(--sp) = 0xdeadc0de;         // Stack filler
        *(--sp) = (uint32_t)exit_fn;  // lr, where we go on exit
        *(--sp) = 0x00000004;         // Stack Adjust
    } else {
        *(--sp) = (uint32_t)exit_fn;  // lr, where we go on exit
        *(--sp) = 0x00000000;         // Stack Adjust
    }
    */

    p->stack_ptr = sp;
    return p;
}
示例#7
0
文件: pthread.c 项目: kstraube/hysim
/* Do whatever init you want.  Return a uthread representing thread0 (int
 * main()) */
struct uthread *pth_init(void)
{
	struct mcs_lock_qnode local_qn = {0};
	/* Tell the kernel where and how we want to receive events.  This is just an
	 * example of what to do to have a notification turned on.  We're turning on
	 * USER_IPIs, posting events to vcore 0's vcpd, and telling the kernel to
	 * send to vcore 0.  Note sys_self_notify will ignore the vcoreid pref.
	 * Also note that enable_kevent() is just an example, and you probably want
	 * to use parts of event.c to do what you want. */
	enable_kevent(EV_USER_IPI, 0, EVENT_IPI);

	/* Handle syscall events.  Using small ev_qs, with no internal ev_mbox. */
	ev_handlers[EV_SYSCALL] = pth_handle_syscall;
	/* Set up the per-vcore structs to track outstanding syscalls */
	sysc_mgmt = malloc(sizeof(struct sysc_mgmt) * max_vcores());
	assert(sysc_mgmt);
	for (int i = 0; i < max_vcores(); i++) {
		/* Set up each of the per-vcore syscall event queues so that they point
		 * to the VCPD/default vcore mailbox (for now)  Note you'll need the
		 * vcore to be online to get the events (for now). */
		sysc_mgmt[i].ev_q.ev_mbox =  &__procdata.vcore_preempt_data[i].ev_mbox;
		sysc_mgmt[i].ev_q.ev_flags = EVENT_IPI;		/* totally up to you */
		sysc_mgmt[i].ev_q.ev_vcore = i;
		/* Init the list and other data */
		TAILQ_INIT(&sysc_mgmt[i].pending_syscs);
		sysc_mgmt[i].handling_overflow = FALSE;
	}
	/* Create a pthread_tcb for the main thread */
	pthread_t t = (pthread_t)calloc(1, sizeof(struct pthread_tcb));
	assert(t);
	t->id = get_next_pid();
	assert(t->id == 0);
	/* Put the new pthread on the active queue */
	mcs_lock_notifsafe(&queue_lock, &local_qn);
	threads_active++;
	TAILQ_INSERT_TAIL(&active_queue, t, next);
	mcs_unlock_notifsafe(&queue_lock, &local_qn);
	return (struct uthread*)t;
}
示例#8
0
文件: proc.c 项目: jack2684/yalnix
/* Init a dummy idle proc
 */
void init_idle_proc() {
    idle_proc = (pcb_t*) malloc(sizeof(pcb_t));
    if(!idle_proc) {
        log_err("Cannot malloc idle proc!");
        return;
    }
    bzero(idle_proc, sizeof(pcb_t));
    idle_proc->user_context.pc = DoDoIdle;
    idle_proc->user_context.sp = (void *)kernel_memory.stack_low;
    //idle_proc->user_context.ebp = (void *)kernel_memory.stack_low;
    //idle_proc->user_context.code = YALNIX_NOP;
    //idle_proc->user_context.vector = TRAP_KERNEL;
    idle_proc->page_table = (pte_t*) malloc(sizeof(pte_t) * GET_PAGE_NUMBER(VMEM_1_SIZE));
    idle_proc->kernel_stack_pages = (pte_t*) malloc(sizeof(pte_t) * KERNEL_STACK_MAXSIZE / PAGESIZE);
    map_page_to_frame(idle_proc->page_table, 0, GET_PAGE_NUMBER(VMEM_1_SIZE), PROT_READ);
    idle_proc->pid = get_next_pid();
    idle_proc->state = READY;
    idle_proc->init_done = 0;

    //init_process_kernel(idle_proc); 
    return;
}
示例#9
0
文件: proc.c 项目: jack2684/yalnix
/* A general function to initialize user proc
 *
 * @return: A pointer to the newly created pcb;
 *          NULL if creation fails
 */
pcb_t *init_user_proc(pcb_t* parent) {
    // Create pcb
    pcb_t *proc = (pcb_t*) malloc(sizeof(pcb_t));
    if(!proc) {
        log_err("Cannot malloc user proc!");
        return NULL;
    }
    bzero(proc, sizeof(pcb_t));
    
    // Create page table
    proc->page_table = (pte_t*) malloc(sizeof(pte_t) * GET_PAGE_NUMBER(VMEM_1_SIZE));
    if(!proc->page_table) {
        log_err("proc->page_table cannot be malloc!");
        return NULL;
    }
    bzero(proc->page_table, sizeof(pte_t) * GET_PAGE_NUMBER(VMEM_1_SIZE));
    
    // Create kernel stack page table
    proc->kernel_stack_pages = (pte_t*) malloc(sizeof(pte_t) * KERNEL_STACK_MAXSIZE / PAGESIZE);
    if(!proc->kernel_stack_pages) {
        log_err("proc->kernel_stack_pages cannot be malloc!");
        return NULL;
    }
    bzero(proc->kernel_stack_pages, sizeof(pte_t) * KERNEL_STACK_MAXSIZE / PAGESIZE);
   
    // Init vitals
    proc->init_done = 0;
    proc->parent = (struct y_PBC*)parent;
    proc->children = dlist_init();
    proc->zombie = dlist_init();
    proc->pid = get_next_pid();
    if(parent) {
        dlist_add_tail(parent->children, proc);
    }
    proc->state = READY;
    proc->wait_zombie = 0;
    return proc;
}
示例#10
0
static gboolean show_task(TraceViewStore *store, struct pevent *pevent,
			  struct record *record, gint pid)
{
	gint event_id;

	if (view_task(store, pid))
		return TRUE;

	event_id = pevent_data_type(pevent, record);

	if (store->sched_switch_next_field &&
	    event_id == store->sched_switch_event->id) {
		/* show sched switch to task */
		pid = get_next_pid(store, pevent, record);
		if (view_task(store, pid))
			return TRUE;
	}

	if (store->sched_wakeup_pid_field &&
	    event_id == store->sched_wakeup_event->id) {
		/* show sched switch to task */
		pid = get_wakeup_pid(store, pevent, record);
		if (view_task(store, pid))
			return TRUE;
	}

	if (store->sched_wakeup_new_pid_field &&
	    event_id == store->sched_wakeup_new_event->id) {
		/* show sched switch to task */
		pid = get_wakeup_new_pid(store, pevent, record);
		if (view_task(store, pid))
			return TRUE;
	}

	return FALSE;
}
示例#11
0
/**
 * \private
 * create a pcb with all the needed value at the specified location
 */
uint32_t
create_proc(char *name, uint32_t prio, uint32_t argc, char **params)
{
  uint32_t       *i, j;
  int32_t         pid;
  pcb            *p;
  prgm           *prg;

  //kdebug_println("Create process in");

  if (name == NULL)
    return NULLPTR;

  if (prio > MAX_PRI || prio < MIN_PRI)
    return INVARG;


  if (pcb_counter <= MAXPCB)
  {
    /*
     * Allocate a pcb
     */
    p = alloc_pcb();

    if (p == NULL)
      return OUTOMEM;

    /*
     * Reset the pcb
     */
    pcb_reset(p);

    /*
     * Check that the program exist
     */
    prg = search_prgm(name);

    if (prg == NULL)
      return INVARG;

    /*
     * Set the name
     */
    pcb_set_name(p, name);

    /*
     * init the program counter
     */
    pcb_set_epc(p, (uint32_t) prg->address);

    /*
     * get a pid
     */
    pid = get_next_pid();

    if (pid < 0)
      return pid;               /* contain an error code */

    pcb_set_pid(p, pid);        /* set the pid */

    pcb_set_pri(p, prio);       /* set the priority */

    /*
     * Set the supervisor of the process, which is the one we ask for the creation
     * or -1 if the system ask.
     * This value is in the global variable current_pcb
     */
    if (current_pcb != NULL)
    {
      pcb_set_supervisor(p, pcb_get_pid(current_pcb));
      pcb_set_supervised(current_pcb, pid);
    }
    else
      pcb_set_supervisor(p, -1);

    /*
       <<<<<<< HEAD:src/kernel/kprocess.c
       <<<<<<< HEAD:src/kernel/kprocess.c
       * Set the parameters of the function
     */
    //p->registers.a_reg[0] = (params == NULL) ? 0 : stoi(get_arg(params, 0)) + 1;
    //p->registers.a_reg[1] = (uint32_t) params;   /* the adresse of the first arg */

    if (params != NULL)
    {
      p->registers.a_reg[0] = argc + 1;
      p->registers.a_reg[1] = (uint32_t) params;
    }
    else
    {
      p->registers.a_reg[0] = 0;
      p->registers.a_reg[1] = 0;
    }

    /*
       =======
       >>>>>>> 3e4887fd7d8130975ae6c220ed2077f5f2538be9:src/kernel/kprocess.c
       * Set the stack pointer
       =======
       * Set the stack pointer
       >>>>>>> ef0b08729fd10e82db039bea92d2ce232b3a027b:src/kernel/kprocess.c
     */
    i = allocate_stack(pcb_get_pid(p));

    if (i == NULL)
      return OUTOMEM;

    /*
     * We add the arg on the stack
     */
    //kprint("sp set\n");

    if (params != NULL)
    {
      //kprint((char *) params);
      //kprint("params not null\n");
      //kprint(itos((uint32_t) i, c));
      //kprint("\n");
      i = (uint32_t *) ((uint32_t) i - (ARG_SIZE * (argc + 1) * sizeof(char))); /* set the sp after the arg */
      //kprint(itos((uint32_t) i, c));
      //kprint("\n");
      pcb_set_sp(p, (uint32_t) i);      /* set the stack pointer */

      for (j = 0;
           j < (argc + 1) * (ARG_SIZE * sizeof(char) / sizeof(uint32_t)); j++)
      {
        //kprint("Copy params\n");
        *i = (uint32_t) * params;
        //kprint("Param copied\n");
        //i += ARG_SIZE * sizeof(char);
        i++;
        (uint32_t *) params++;
      }
      //kprint((char *) pcb_get_sp(p));
    }
    else
      pcb_set_sp(p, (uint32_t) i);

    //kprint("copy arg done\n");

    /*
     * Set the parameters of the function
     * The begin of the parameters are pointed by the stack pointer
     */
    if (params != NULL)
    {
      p->registers.a_reg[0] = argc + 1;
      p->registers.a_reg[1] = (uint32_t) pcb_get_sp(p);
    }
    else
    {
      p->registers.a_reg[0] = 0;
      p->registers.a_reg[1] = 0;
    }

    /*
     * Set the state
     */

    pcb_set_state(p, READY);

    /*
     * Set the last error
     */
    pcb_set_error(p, OMGROXX);

    /*
     * The pcb is no more empty
     */
    pcb_set_empty(p, FALSE);

    /*
     * Now we can add the pcb to the ready list
     */
    if (pls_add(&plsready, p) == OUTOMEM)
    {
      /*
       * Adding fail, don't forget to dealloc every allocated stuff
       */
      deallocate_stack(pcb_get_pid(p));
      pcb_reset(p);
      return OUTOMEM;
    }

    /*
     * Everything goes well, we add one to the pcb_counter
     */
    pcb_counter++;

  }
  else
    return OUTOMEM;

  //kdebug_println("Create process out");

  return pid;
}