Beispiel #1
0
/*
 * Timer that loops up to CHECK_DTS_MAX_ATTEMPTS times to see if we have a
 * connection to DTS yet.  If a connection has been made (in collapsed mode
 * this takes roughly 2ms) then an updated component inventory will be
 * requested.  If no connection is made, then the inventory update is skipped
 * and the init_phase is scheduled next.
 */
static void check_dts_connected(rwsched_CFRunLoopTimerRef timer, void * ctx)
{
  struct wait_on_dts_cls * cls;

  cls = (struct wait_on_dts_cls *)ctx;

  if (++cls->attempts >= CHECK_DTS_MAX_ATTEMPTS) {
    rwmain_trace_info(
        cls->rwmain,
        "No connection to DTS after %f seconds, skipping inventory update",
        (double)CHECK_DTS_MAX_ATTEMPTS * (1.0 / (double)CHECK_DTS_FREQUENCY));
    schedule_next(cls->rwmain, init_phase, 0, NULL);
    goto finished;
  }

  if (rwdts_get_router_conn_state(cls->rwmain->dts) == RWDTS_RTR_STATE_UP) {
    rwmain_trace_info(
        cls->rwmain,
        "Connected to DTS after %f seconds, scheduling inventory update",
        (double)cls->attempts * (1.0 / (double)CHECK_DTS_FREQUENCY));
    schedule_next(cls->rwmain, request_inventory_update, 0, NULL);
    goto finished;
  }

  return;

finished:
  rwsched_tasklet_CFRunLoopTimerRelease(cls->rwmain->rwvx->rwsched_tasklet, timer);
  free(cls);
}
Beispiel #2
0
/*
  The gtthread_exit() function is analogous to pthread_exit.
 */
void gtthread_exit(void* retval){
  gtthread_int_t *self;
  sigset_t oldset;

  /* Block alarms */
  sigprocmask(SIG_BLOCK, &vtalrm, &oldset);

  /* Remove the thread from run_queue */
  self = (gtthread_int_t *) steque_pop(&run_queue);

  /* Set the return value */
  self->retval = retval;

  /* Mark thread as completed */
  self->completed = 1;

  /* Reschedule joined threads */
  reschedule_joined(self);

  /* Need to reschedule so we don't just drop back
     into parent context */
  schedule_next(self);

  /* Unblock alarms */
  sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
}
Beispiel #3
0
/*
 * Called when we get a response from DTS with any additional component
 * definitions added to the inventory via runtime configuration.
 *
 * Adds any new components to the manifest held by rwvcs and then schedules
 * the init_phase.
 */
static void on_inventory_update(rwdts_xact_t * xact, rwdts_xact_status_t* xact_status, void * ud)
{
  //rw_status_t status;
  struct rwmain_gi * rwmain;
  rwvcs_instance_ptr_t rwvcs;
  vcs_manifest_inventory * ret_inventory;
  vcs_manifest_inventory * inventory;


  rwmain = (struct rwmain_gi *)ud;
  rwvcs = rwmain->rwvx->rwvcs;
  RW_CF_TYPE_VALIDATE(rwvcs, rwvcs_instance_ptr_t);

  if (xact_status->status == RWDTS_XACT_FAILURE || xact_status->status == RWDTS_XACT_ABORTED) {
    rwmain_trace_info(rwmain, "Lookup of component probably failed");
    goto done;
  }

  rwmain_trace_info(rwmain, "Updating inventory");

  rwdts_query_result_t *qrslt = rwdts_xact_query_result(xact, 0);  
  while (qrslt) {
    ret_inventory = (vcs_manifest_inventory*)(qrslt->message);
    RW_ASSERT(ret_inventory);
    RW_ASSERT(ret_inventory->base.descriptor == RWPB_G_MSG_PBCMD(RwManifest_data_Manifest_Inventory));

    inventory = rwvcs->pb_rwmanifest->inventory;
    for (size_t i = 0; i < ret_inventory->n_component; ++i) {
      // Any updates to the static manifest are going to be ignored.
      if (rwvcs_manifest_have_component(rwvcs, ret_inventory->component[i]->component_name)) {
        continue;
      }

      inventory->component = (vcs_manifest_component **)realloc(
          inventory->component,
          sizeof(vcs_manifest_component *) * (inventory->n_component + 1));
      RW_ASSERT(inventory->component);
      inventory->component[inventory->n_component] = (vcs_manifest_component*)protobuf_c_message_duplicate(
          NULL,
          &ret_inventory->component[i]->base,
          ret_inventory->component[i]->base.descriptor);
      inventory->n_component++;

      rwmain_trace_info(
          rwmain,
          "Updating inventory with %s",
          ret_inventory->component[i]->component_name);
    }
    qrslt = rwdts_xact_query_result(xact, 0);
  }

done:
  schedule_next(rwmain, init_phase, 0, NULL);
}
Beispiel #4
0
struct thread *syscall_exit(struct thread *image) {

	if (image->proc->pid == 1) {
		debug_panic("init died");
	}

	process_switch(process_get(1));
	process_kill(image->proc);

	return thread_switch(image, schedule_next());
}
Beispiel #5
0
void eval_cd(void)
{
	int tag = ((cd*)input)->col_tag;
	switch(tag)
	{
	case LIVEQ:
		schedule_next(((cd*)input)->content);
		break;
	case LIST:
		schedule_next(trigger);
		schedule_next(((cd*)input)->content);
		push(collections,NULL);
		push(wait_stack,collector);
		break;
	case LITLIST:
	case QUOTE:
		execute_waiter();
		break;
	default:
		debug("unknown col... ");
		break;
	}
}
Beispiel #6
0
void parse_string(void)
{
	string* the_str = ((string*)input);
	char* code = get_str_content(the_str);
	int index;
	prepare_to_parse();
	for(index=0;index<the_str->length;index++)
	{
		parse_current_char();
		current_char = code[index];
	}
	finalize_quote();
	schedule_next(*lexical_stack);
	pop(wait_stack);
}
Beispiel #7
0
/*
  The gtthread_yield() function is analogous to pthread_yield, causing
  the calling thread to relinquish the cpu and place itself at the
  back of the schedule queue.
 */
void gtthread_yield(void){
  gtthread_int_t *old;
  sigset_t oldset;

  /* Block alarms */
  sigprocmask(SIG_BLOCK, &vtalrm, &oldset);

  /* Put current thread at end of run queue */
  old = (gtthread_int_t *) steque_pop(&run_queue);
  steque_enqueue(&run_queue, old);
  
  /* Start running the new thread */
  schedule_next(old);

  /* Unblock alarms */
  sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
}
Beispiel #8
0
/*
  The gtthread_join() function is analogous to pthread_join.
  All gtthreads are joinable.
 */
int gtthread_join(gtthread_t thread, void **status){
  gtthread_int_t *target, *self;
  sigset_t oldset;
  
  /* Block alarms */
  sigprocmask(SIG_BLOCK, &vtalrm, &oldset);

  /* Find the thread id */
  target = find_thread(thread);

  if (target != NULL) {

    /* If the target thread isn't complete, need to schedule another thread */
    if (!target->completed) {
      // 2. Pop this thread off of the main run queue
      self = (gtthread_int_t *) steque_pop(&run_queue);

      // 3. Enqueue this thread on the target thread run queue
      steque_enqueue(&target->join_queue, self);

      // 4. Schedule the next thread, since this is no longer in the run queue
      schedule_next(self);

      /* Unblock alarms */
      sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
    } else {
      /* Unblock alarms */
      sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
    }

    // 5. Set status
    if (status != NULL) {
      *status = target->retval;
    }

    return 0;
  } else {
    /* Unblock alarms */
    sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);

    // target thread not found
    return 1;
  }
}
Beispiel #9
0
static void check_parent_started(rwsched_CFRunLoopTimerRef timer, void * ctx)
{
  struct rwmain_gi * rwmain = (struct rwmain_gi *)ctx;
  rw_component_info c_info;

  rw_status_t status = rwvcs_rwzk_lookup_component(rwmain->rwvx->rwvcs, rwmain->parent_id, &c_info);
  RW_ASSERT(status != RW_STATUS_FAILURE);
  if (status == RW_STATUS_NOTFOUND) {
    return;
  }
  else {
    status = rwmain_bootstrap(rwmain);
    RW_ASSERT(status == RW_STATUS_SUCCESS);

    struct wait_on_dts_cls *cls = (struct wait_on_dts_cls *)malloc(sizeof(struct wait_on_dts_cls));
    RW_ASSERT(cls);
    cls->rwmain = rwmain;
    cls->attempts = 0;
    schedule_next(rwmain, check_dts_connected, CHECK_DTS_FREQUENCY, cls);
  }

  rwsched_tasklet_CFRunLoopTimerRelease(rwmain->rwvx->rwsched_tasklet, timer);
}
Beispiel #10
0
void eval_symbol(void)
{
	symbol* the_sym = (symbol*)input;
	if(the_sym->meta_level == 0)
	{
		binding* the_binding = find_binding_delegating(the_sym->id,current_scope);
		if(the_binding != NULL)
		{
			void* value = the_binding->value;
			if(value != the_sym)
				schedule_next(value);
			else /* the symbol is a singleton */
				execute_waiter(); 
		}
		else
			printf("error:\nsymbol :%s is bound to nothing in this accumulative context", get_symbol_name(the_sym->id));
	}
	else
	{
		input = make_symbol(the_sym->id,the_sym->meta_level-1);
		execute_waiter();
	}
	
}
Beispiel #11
0
void evaluate(void)
{
	schedule_next(((cd*)input)->content);
	while(true) eval_current();
}
Beispiel #12
0
struct thread *init(struct multiboot *mboot, uint32_t mboot_magic) {
	struct process *idle, *init;
	struct module *module;
	struct memory_map *mem_map;
	size_t mem_map_count, i, addr;
	uintptr_t boot_image_size;
	void *boot_image;
	struct elf32_ehdr *init_image;
	struct elf32_ehdr *dl_image;

	/* initialize debugging output */
	debug_init();
	debug_printf("Rhombus Operating System Kernel v0.8a\n");

	/* check multiboot header */
	if (mboot_magic != 0x2BADB002) {
		debug_panic("bootloader is not multiboot compliant");
	}

	/* touch pages for the kernel heap */
	for (i = KSPACE; i < KERNEL_HEAP_END; i += SEGSZ) {
		page_touch(i);
	}

	/* identity map kernel boot frames */
	for (i = KSPACE + KERNEL_BOOT; i < KSPACE + KERNEL_BOOT_END; i += PAGESZ) {
		page_set(i, page_fmt(i - KSPACE, PF_PRES | PF_RW));
	}

	/* parse the multiboot memory map to find the size of memory */
	mem_map       = (void*) (mboot->mmap_addr + KSPACE);
	mem_map_count = mboot->mmap_length / sizeof(struct memory_map);

	for (i = 0; i < mem_map_count; i++) {
		if (mem_map[i].type == 1 && mem_map[i].base_addr_low <= 0x100000) {
			for (addr = 0; addr < mem_map[i].length_low; addr += PAGESZ) {
				frame_add(mem_map[i].base_addr_low + addr);
			}
		}
	}

	/* bootstrap process 0 (idle) */
	idle = process_alloc();
	idle->space = cpu_get_cr3();
	idle->user  = 0;

	/* fork process 1 (init) and switch */
	init = process_clone(idle, NULL);
	process_switch(init);

	/* get multiboot module information */
	if (mboot->mods_count < 3) {
		if (mboot->mods_count < 2) {
			if (mboot->mods_count < 1) {
				debug_panic("no boot or init or dl modules found");
			}
			else {
				debug_panic("no boot or dl modules found");
			}
		}
		else {
			debug_panic("no dl module found");
		}
	}
	module     = (void*) (mboot->mods_addr + KSPACE);
	init_image = (void*) (module[0].mod_start + KSPACE);
	boot_image = (void*) (module[1].mod_start + KSPACE);
	dl_image   = (void*) (module[2].mod_start + KSPACE);
	boot_image_size = module[1].mod_end - module[1].mod_start;

	/* move boot image to BOOT_IMAGE in userspace */
	mem_alloc(BOOT_IMAGE, boot_image_size, PF_PRES | PF_USER | PF_RW);
	memcpy((void*) BOOT_IMAGE, boot_image, boot_image_size);

	/* bootstrap thread 0 in init */
	thread_bind(init->thread[0], init);
	init->thread[0]->useresp = init->thread[0]->stack + SEGSZ;
	init->thread[0]->esp     = (uintptr_t) &init->thread[0]->num;
	init->thread[0]->ss      = 0x23;
	init->thread[0]->ds      = 0x23;
	init->thread[0]->cs      = 0x1B;
	init->thread[0]->eflags  = cpu_get_eflags() | 0x3200; /* IF, IOPL = 3 */

	/* bootstrap idle thread */
	idle->thread[0] = &__idle_thread;
	__idle_thread.proc = idle;

	/* load dl */
	if (elf_check_file(dl_image)) {
		debug_panic("dl.so is not a valid ELF executable");
	}
	elf_load_file(dl_image);

	/* execute init */
	if (elf_check_file(init_image)) {
		debug_panic("init is not a valid ELF executable");
	}
	elf_load_file(init_image);
	init->thread[0]->eip = init_image->e_entry;

	/* register system calls */
	int_set_handler(SYSCALL_SEND, syscall_send);
	int_set_handler(SYSCALL_DONE, syscall_done);
	int_set_handler(SYSCALL_WHEN, syscall_when);
	int_set_handler(SYSCALL_RIRQ, syscall_rirq);
	int_set_handler(SYSCALL_ALSO, syscall_also);
	int_set_handler(SYSCALL_STAT, syscall_stat);
	int_set_handler(SYSCALL_PAGE, syscall_page);
	int_set_handler(SYSCALL_PHYS, syscall_phys);
	int_set_handler(SYSCALL_FORK, syscall_fork);
	int_set_handler(SYSCALL_EXIT, syscall_exit);
	int_set_handler(SYSCALL_STOP, syscall_stop);
	int_set_handler(SYSCALL_WAKE, syscall_wake);
	int_set_handler(SYSCALL_GPID, syscall_gpid);
	int_set_handler(SYSCALL_TIME, syscall_time);
	int_set_handler(SYSCALL_USER, syscall_user);
	int_set_handler(SYSCALL_AUTH, syscall_auth);
	int_set_handler(SYSCALL_PROC, syscall_proc);
	int_set_handler(SYSCALL_KILL, syscall_kill);
	int_set_handler(SYSCALL_VM86, syscall_vm86);
	int_set_handler(SYSCALL_NAME, syscall_name);
	int_set_handler(SYSCALL_REAP, syscall_reap);

	/* register fault handlers */
	int_set_handler(FAULT_DE, fault_float);
	int_set_handler(FAULT_DB, fault_generic);
	int_set_handler(FAULT_NI, fault_generic);
	int_set_handler(FAULT_BP, fault_generic);
	int_set_handler(FAULT_OF, fault_generic);
	int_set_handler(FAULT_BR, fault_generic);
	int_set_handler(FAULT_UD, fault_generic);
	int_set_handler(FAULT_NM, fault_nomath);
	int_set_handler(FAULT_DF, fault_double);
	int_set_handler(FAULT_CO, fault_float);
	int_set_handler(FAULT_TS, fault_generic);
	int_set_handler(FAULT_NP, fault_generic);
	int_set_handler(FAULT_SS, fault_generic);
	int_set_handler(FAULT_GP, fault_gpf);
	int_set_handler(FAULT_PF, fault_page);
	int_set_handler(FAULT_MF, fault_float);
	int_set_handler(FAULT_AC, fault_generic);
	int_set_handler(FAULT_MC, fault_generic);
	int_set_handler(FAULT_XM, fault_nomath);

	/* start timer (for preemption) */
	timer_set_freq(64);

	/* initialize FPU/MMX/SSE */
	cpu_init_fpu();

	/* drop to usermode, scheduling the next thread */
	debug_printf("dropping to usermode\n");
	return thread_switch(NULL, schedule_next());
}
Beispiel #13
0
int main ()
{
    hdk_init_platform_endian();

    // hardware related initialization.
    haddock_hal_init();
    
    // kernel resource initialization.
    haddock_process_module_init();
    haddock_timer_module_init();

#if defined HDK_CFG_POWER_SAVING_ENABLE && HDK_CFG_POWER_SAVING_ENABLE == OS_TRUE
    haddock_power_manager_module_init();
#endif
    
    os_user_processes_init();
    
    static struct process *proc = NULL;
    /**
     * \remark We use @_signal to backup the process's signal_bv_t before the
     *         execution of @proc->entry to avoid the race conditions between 
     *         interrupts (who may want to set_signal) and @proc->entry (who
     *         may want to clear_signal).
     */
    signal_bv_t _signal = 0;
    interrupt_state_t _state;
    
    while (OS_TRUE) {
        __increment_main_loop_counter();
        
        __get_kernel_timetick_now(); // also updated @haddock_time_tick_now
        haddock_timer_update_routine();

        proc = schedule_next();
        if (proc) {
#if defined HDK_CFG_POWER_SAVING_ENABLE && HDK_CFG_POWER_SAVING_ENABLE == OS_TRUE
            haddock_power_status = POWER_STATUS_RUNNING;
#endif
            
#if defined HDK_CFG_POWER_SAVING_ENABLE && HDK_CFG_POWER_SAVING_ENABLE == OS_TRUE
            if (proc->is_wakeup == OS_FALSE) {
                haddock_disable_power_conserve(proc);
            }
#endif

            HDK_ENTER_CRITICAL_SECTION(_state);
            _signal = proc->signal;
            proc->signal = 0;
            HDK_EXIT_CRITICAL_SECTION(_state);

            haddock_assert(proc->entry);
            cur_process_id = proc->_pid;
            
            _signal = proc->entry(proc->_pid, _signal);
            
            HDK_ENTER_CRITICAL_SECTION(_state);
            proc->signal |= _signal;
            HDK_EXIT_CRITICAL_SECTION(_state);
        } else {
#if defined (HDK_USER_CFG_HAL_TARGET) && HDK_USER_CFG_HAL_TARGET == HAL_TARGET_PC
            if (os_no_more_timers()) { // no more timers.
                exit(0);
            }
#endif

#if defined HDK_CFG_POWER_SAVING_ENABLE && HDK_CFG_POWER_SAVING_ENABLE == OS_TRUE
            haddock_power_conserve_routine();
#endif
        }
    }
    
    return 0;
}
Beispiel #14
0
struct thread *thread_exit(struct thread *image) {
	thread_free(image);

	return thread_switch(NULL, schedule_next());
}