task_t *new_thread(team_t *team, uint32 ip, int kernelspace) { task_t *t; int stack; void *addr; int i; /* xxx this should be cleaner -- have a flag to area_create perhaps */ for(i=1023;i>0;i--){ if(!team->aspace->ptab[i]) break; } stack = area_create(team->aspace, 4096, i*4096, &addr, 0); if(!stack) panic("cannot create a stack area. eek"); t = task_create(team, ip, i*4096+4092, kernelspace); t->ustack = (void *) (i << 12); t->stack_area = rsrc_find(RSRC_AREA,stack); rsrc_bind(&t->rsrc, RSRC_TASK, team); t->flags = tREADY; if(!kernelspace) { rsrc_enqueue(run_queue, t); live_tasks++; } return t; }
/** Try to enlarge any of the heap areas. * * If successful, allocate block of the given size in the area. * Should be called only inside the critical section. * * @param size Gross size of item to allocate (bytes). * @param align Memory address alignment. * * @return Allocated block. * @return NULL on failure. * */ static void *heap_grow_and_alloc(size_t size, size_t align) { if (size == 0) return NULL; /* First try to enlarge some existing area */ for (heap_area_t *area = first_heap_area; area != NULL; area = area->next) { if (area_grow(area, size + align)) { heap_block_head_t *first = (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area); void *addr = malloc_area(area, first, NULL, size, align); malloc_assert(addr != NULL); return addr; } } /* Eventually try to create a new area */ if (area_create(AREA_OVERHEAD(size + align))) { heap_block_head_t *first = (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area); void *addr = malloc_area(last_heap_area, first, NULL, size, align); malloc_assert(addr != NULL); return addr; } return NULL; }
void __libc_init_vfs (void) { vfs_public_port = namer_find ("vfs", 1); vfs_local_port = port_create (vfs_public_port,"vfs_public_port"); filename_area = area_create (0x1000, 0, (void **) &nameptr, 0); __vfs_openconn (vfs_local_port, filename_area); }
RID Physics2DServerSW::space_create() { Space2DSW *space = memnew(Space2DSW); RID id = space_owner.make_rid(space); space->set_self(id); RID area_id = area_create(); Area2DSW *area = area_owner.get(area_id); ERR_FAIL_COND_V(!area, RID()); space->set_default_area(area); area->set_space(space); area->set_priority(-1); return id; };
Area* column_new(View *v, Area *pos, int scrn, uint w) { Area *a; assert(!pos || !pos->floating && pos->screen == scrn); a = area_create(v, pos, scrn, w); return a; #if 0 if(!a) return nil; view_arrange(v); view_update(v); #endif }
DIR *_opendir (const char *name) { int area; void *ptr; msg_hdr_t msg; vfs_cmd_t vc; vfs_res_t vr; DIR *dirp; strlcpy (nameptr, name, BLT_MAX_NAME_LENGTH); area = area_create (0x2000, 0, &ptr, 0); vc.cmd = VFS_OPENDIR; vc.data[0] = 0; vc.data[1] = area; vc.data[2] = 0; vc.data[3] = 0x2000; msg.src = vfs_local_port; msg.dst = vfs_remote_port; msg.data = &vc; msg.size = sizeof (vfs_cmd_t); old_port_send (&msg); msg.src = vfs_remote_port; msg.dst = vfs_local_port; msg.data = &vr; msg.size = sizeof (vfs_res_t); old_port_recv (&msg); if (vr.status != VFS_OK) { errno = vr.errno; return NULL; } //_printf ("libc: opendir got fd %d\n", vr.data[0]); dirp = malloc (sizeof (DIR)); dirp->fd = vr.data[0]; dirp->hoffset = 0; dirp->head = ptr; dirp->current = ptr; dirp->more = vr.data[2]; dirp->len = vr.data[1]; dirp->left = dirp->len; return dirp; }
RID PhysicsServerSW::space_create() { SpaceSW *space = memnew( SpaceSW ); RID id = space_owner.make_rid(space); space->set_self(id); RID area_id = area_create(); AreaSW *area = area_owner.get(area_id); ERR_FAIL_COND_V(!area,RID()); space->set_default_area(area); area->set_space(space); area->set_priority(-1); RID sgb = body_create(); body_set_space(sgb,id); body_set_mode(sgb,BODY_MODE_STATIC); space->set_static_global_body(sgb); return id; };
int _open (const char *path, int flags, mode_t mode) { int i, area; void *ptr; msg_hdr_t msg; vfs_cmd_t vc; vfs_res_t vr; vfs_fd *fd; strlcpy (nameptr, path, BLT_MAX_NAME_LENGTH); area = area_create (0x2000, 0, &ptr, 0); vc.cmd = VFS_OPEN; vc.data[0] = 0; vc.data[1] = area; vc.data[2] = 0; vc.data[3] = 0x2000; msg.src = vfs_local_port; msg.dst = vfs_remote_port; msg.data = &vc; msg.size = sizeof (vfs_cmd_t); old_port_send (&msg); msg.src = vfs_remote_port; msg.dst = vfs_local_port; msg.data = &vr; msg.size = sizeof (vfs_res_t); old_port_recv (&msg); if (vr.status != VFS_OK) { errno = vr.errno; return -1; } //_printf ("libc: open got %d %d %d\n", vr.data[0], vr.data[1], vr.data[2]); fd = malloc (sizeof (vfs_fd)); i = _fdl_alloc_descriptor (&vfs_fdl_handler, fd); fd->buf = ptr; fd->offset = 0; fd->srv_fd = vr.data[0]; fd->length = vr.data[1]; fd->more = vr.data[2]; return i; }
int console_main(void) { int err,i; area_create(0x2000, 0, &screen, AREA_PHYSMAP); console_port = port_create(0,"console_listen_port"); send_port = port_create(0,"console_send_port"); port_option(send_port, PORT_OPT_NOWAIT, 1); err = namer_register(console_port,"console"); init_virtscreen(&statbar, 1, 80); statbar.back = statbar.data; statbar.data = (unsigned short *) (((uint32) screen) + 80*24*2); statbar.lock = sem_create(1,"statbar_lock"); for(i=0;i<10;i++){ init_virtscreen(&con[i], 24, 80); con[i].back = con[i].data; con[i].lock = sem_create(1,"vscr_lock"); vputs(&con[i],CLEAR); } load(&con[0]); status(0); if(err) vprintf(active,"console: the namer hates us\n"); else #ifdef CONSOLE_DEBUG vprintf(active,"console: " FG_GREEN "online." FG_WHITE "\n"); #else ; #endif thr_create(keyboard_irq_thread, NULL, "console:kbd"); ready = 1; console_thread(); return 0; }
/** Initialize the heap allocator * * Create initial heap memory area. This routine is * only called from libc initialization, thus we do not * take any locks. * */ void __malloc_init(void) { if (!area_create(PAGE_SIZE)) abort(); }
int main (void) { int area, sarea; char *c, *rcboot, *line, *boot_servers, **params; int i, space, p_argc, boot, fd, len, total, prog, filenum; void *ptr; boot_dir *dir; line = malloc (256); boot_servers = malloc (256); if (!(boot = area_clone (3, 0, (void **) &dir, 0))) { os_console ("no uberarea; giving up"); os_debug (); for (;;) ; /* fatal */ return 0; } else if ((filenum = boot_get_num (dir, "rc.boot")) < 0) { os_console ("no /boot/rc.boot; do you know what you're doing?"); os_debug (); } else { *line = *boot_servers = len = total = 0; rcboot = boot_get_data (dir, filenum); while (total < dir->bd_entry[filenum].be_vsize) { line[len++] = *rcboot++; total++; if (line[len - 1] == '\n') { line[len-- - 1] = 0; for (i = space = 0, p_argc = 2; i < len; i++) if ((line[i] == ' ') && !space) space = 1; else if ((line[i] != ' ') && space) { p_argc++; space = 0; } if ((*line != '#') && *line) { params = malloc (sizeof (char *) * p_argc); c = line; for (i = 0; i < p_argc - 1; i++) { for (len = 0; c[len] && (c[len] != ' '); len++) ; params[i] = malloc (len + 1); strlcpy (params[i], c, len + 1); c += len + 1; } params[i] = NULL; if (!strcmp (params[0], "exit")) os_terminate (1); prog = boot_get_num (dir, params[0]); area = area_create (dir->bd_entry[prog].be_vsize, 0, &ptr, 0); memcpy (ptr, boot_get_data (dir, prog), dir->bd_entry[prog].be_vsize); sarea = area_create (0x1000, 0, &ptr, 0); strlcat (boot_servers, " ", 256); strlcat (boot_servers, params[0], 256); thr_wait (thr_spawn (0x1074, 0x3ffffd, area, 0x1000, sarea, 0x3ff000, params[0])); } len = 0; } } } /* say hello */ __libc_init_fdl (); __libc_init_console (); __libc_init_vfs (); printf (copyright); printf ("init: bootstrap servers started. [ %s ]\n", boot_servers + 1); /* if we one day pass arguments to init, we will parse them here. */ /* do some more normal stuff */ printf ("init: beginning automatic boot.\n\n"); fd = open ("/boot/rc", O_RDONLY, 0); if (fd < 0) printf ("error opening /boot/rc\n"); else { *line = len = 0; while (read (fd, line + len++, 1) > 0) { if (line[len - 1] == '\n') { /* line[len - 1] = 0; if ((*line != '#') && *line) { // printf ("execing `%s'\n", line); params = malloc (sizeof (char *) * 2); params[0] = malloc (strlen (line) + 1); strcpy (params[0], line); params[1] = NULL; thr_join (thr_detach (run2), 0); } len = 0; */ line[len-- - 1] = 0; for (i = space = 0, p_argc = 2; i < len; i++) if ((line[i] == ' ') && !space) space = 1; else if ((line[i] != ' ') && space) { p_argc++; space = 0; } if ((*line != '#') && *line) { params = malloc (sizeof (char *) * p_argc); c = line; for (i = 0; i < p_argc - 1; i++) { for (len = 0; c[len] && (c[len] != ' '); len++) ; params[i] = malloc (len + 1); strlcpy (params[i], c, len + 1); c += len + 1; } params[i] = NULL; if (!strcmp (params[0], "exit")) os_terminate (1); i = execve (params[0], params, NULL); if(i>0) thr_wait(i); else printf("cannot execute \"%s\"\n",params[0]); } len = 0; } } close (fd); } printf ("init: nothing left to do\n"); return 0; }
void go_kernel(void) { task_t *t; int i,len; void *ptr,*phys; port_t *uberport; area_t *uberarea; team_t *team; for (i = 0, len = 1; (bdir->bd_entry[i].be_type != BE_TYPE_NONE); i++){ len += bdir->bd_entry[i].be_size; } len *= 0x1000; uberport = rsrc_find_port(uberportnum = port_create(0,"uberport")); uberarea = rsrc_find_area(uberareanum = area_create_uber(len, (void *) 0x100000)); kprintf("uberport allocated with rid = %d",uberportnum); kprintf("uberarea allocated with rid = %d",uberareanum); kernel_team = team_create(); rsrc_set_name(&kernel_team->rsrc, "kernel team"); run_queue = rsrc_find_queue(queue_create("run queue",kernel_team)); reaper_queue = rsrc_find_queue(queue_create("reaper queue",kernel_team)); timer_queue = rsrc_find_queue(queue_create("timer queue",kernel_team)); rsrc_set_owner(&uberarea->rsrc,kernel_team); rsrc_set_owner(&uberport->rsrc,kernel_team); for(i=3;bdir->bd_entry[i].be_type;i++){ if(bdir->bd_entry[i].be_type != BE_TYPE_CODE) continue; team = team_create(); t = new_thread(team, 0x1074 /*bdir->bd_entry[i].be_code_ventr*/, 0); current = t; phys = (void *) (bdir->bd_entry[i].be_offset*0x1000 + 0x100000); team->text_area = area_create(team->aspace,bdir->bd_entry[i].be_size*0x1000, 0x1000, &phys, AREA_PHYSMAP); team->heap_id = area_create(team->aspace,0x2000,0x1000 + bdir->bd_entry[i].be_size* 0x1000, &ptr, 0); /* make the thread own it's address space */ /* rsrc_set_owner(&a->rsrc, t); */ if (!strcmp (bdir->bd_entry[i].be_name, "namer")) { rsrc_set_owner(&uberport->rsrc, team); } rsrc_set_name(&t->rsrc,bdir->bd_entry[i].be_name); rsrc_set_name(&team->rsrc,bdir->bd_entry[i].be_name); kprintf("task %X @ 0x%x, size = 0x%x (%s)",t->rsrc.id, bdir->bd_entry[i].be_offset*4096+0x100000, bdir->bd_entry[i].be_size*4096, t->rsrc.name); } kprintf("creating idler..."); idle_task = new_thread(kernel_team, (int) idler, 1); rsrc_set_name((resource_t*)idle_task,"idler"); kprintf("creating grim reaper..."); current = new_thread(kernel_team, (int) reaper, 1); rsrc_set_name((resource_t*)current,"grim reaper"); reaper_sem = sem_create(0,"death toll"); rsrc_enqueue(run_queue, current); live_tasks++; kprintf("creating pager..."); current = pager_task = new_thread(kernel_team, (int) pager, 1); rsrc_set_name((resource_t*)current,"pager"); pager_port_no = port_create(0,"pager port"); pager_sem_no = sem_create(0, "pager sem"); rsrc_enqueue(run_queue, current); live_tasks++; rsrc_set_name((resource_t*)kernel,"kernel"); #ifdef __SMP__ smp_init (); #endif // DEBUGGER(); kprintf("starting scheduler..."); #ifdef __SMP__ if (smp_configured) { smp_final_setup (); kprintf ("smp: signaling other processors"); smp_begin (); } #endif /* * when the new vm stuffas are done, we can at this point discard any * complete pages in the .text.init and .data.init sections of the kernel * by zeroing them and adding them to the free physical page pool. */ current = kernel; current->flags = tDEAD; current->waiting_on = NULL; swtch(); kprintf("panic: returned from scheduler?"); asm("hlt"); }
/* test functions */ static int test_area (AREA_CREATE_INFO * info, int nthreads, void *(*proc) (void *)) { #define MAX_THREADS 64 AREA *area = NULL; pthread_t threads[MAX_THREADS]; char msg[256]; int i; assert (info != NULL); sprintf (msg, "%s(size:%d, count:%d), %d threads", info->name, info->entry_size, info->alloc_cnt, nthreads); begin (msg); /* initialization */ if (nthreads > MAX_THREADS) { return fail ("too many threads"); } /* initialization */ area_init (); area = area_create (info->name, info->entry_size, info->alloc_cnt); if (area == NULL) { return fail ("area create fail"); } /* multithreaded test */ for (i = 0; i < nthreads; i++) { if (pthread_create (&threads[i], NULL, proc, (void *) area) != NO_ERROR) { return fail ("thread create"); } } for (i = 0; i < nthreads; i++) { void *retval; pthread_join (threads[i], &retval); if (retval != NO_ERROR) { return fail ("thread proc error"); } } /* results */ { AREA_BLOCKSET_LIST *blockset; AREA_BLOCK *block; int i, j, blockset_cnt = 0, block_cnt = 0, chunk_count; for (blockset = area->blockset_list; blockset != NULL; blockset = blockset->next) { for (i = 0; i < blockset->used_count; i++) { block = blockset->items[i]; assert (block != NULL); chunk_count = CEIL_PTVDIV (block->bitmap.entry_count, LF_BITFIELD_WORD_SIZE); for (j = 0; j < chunk_count; j++) { if (block->bitmap.bitfield[j]) { return fail ("check bitmap status"); } } block_cnt++; } blockset_cnt++; } printf (" Used %3d blocks(%2d blocksets). ", block_cnt, blockset_cnt); } /* destory */ area_destroy (area); area_final (); return success (); #undef MAX_THREADS }