bool filesys_mkdir (const char *path) { struct dir *dir = NULL; bool success = false; char *name = malloc (NAME_MAX + 1); if (name == NULL) goto done; if (!dir_follow_path (thread_current ()->cwd, path, &dir, name)) goto done; if (dir == NULL) goto done; if (!dir_create_subdir (dir, name)) goto done; success = true; done: dir_close (dir); free (name); return success; }
static unsigned sys_tell(int fd) { if(fd<2 || fd>129) return -1; struct thread *curr = thread_current(); struct list_elem *e; struct opened_file_elem *opened_elem; int check_valid=0; for( e = list_begin(&curr->openfile_list) ; e != list_end(&curr->openfile_list) ; e = list_next(e) ) { opened_elem=list_entry(e,struct opened_file_elem,elem_f); if(opened_elem->fd==fd) { check_valid=0; return file_tell(opened_elem->opened_file); } } if(check_valid==0) return -1; }
/*! Given a mapid, look for and return the corresponding mapid struct * of this process */ struct mmap_elem* find_mmap_elem(mapid_t mapid){ struct list_elem *e; struct thread* t = thread_current(); struct list* m_lst = &(t->mmap_lst); struct mmap_elem* me; /* Check for the validity of this mapid. */ if (mapid == MAP_FAIL && mapid > t->mmapid_max) { exit(-1); } /* Iterate through the mapid list of the process, and check for * the mapid */ for (e = list_begin(m_lst); e != list_end(m_lst); e = list_next(e)){ me = list_entry(e, struct mmap_elem, elem); if (mapid == me->mapid) return me; } exit(-1); }
/* Sleeps for approximately TICKS timer ticks. Interrupts must be turned on. */ void timer_sleep (int64_t ticks) { enum intr_level old_level; int64_t start = timer_ticks (); struct thread *t = thread_current(); if( ticks > 0 ) { t->wake_up_ticks = ticks + start; /* add the thread to the wait list */ old_level = intr_disable(); list_push_back( &wait_list, &( t->elem_wait ) ); intr_set_level( old_level ); ASSERT (intr_get_level () == INTR_ON); /* block the thread */ sema_down( &t->wait_sem ); } }
bool file_elem_spage_table (struct file *file, int32_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes, bool writable) { struct spage_entry *se = malloc (sizeof (struct spage_entry)); if (se == NULL) return false; se->type = 0; se->already_loaded = false; se->pinned = false; se->myfile = file; se->ofs = ofs; se->upage = upage; se->read_bytes = read_bytes; se->zero_bytes = zero_bytes; se->writable = writable; list_push_back (&thread_current ()->spage_list, &se->s_elem); return true; }
void* frame_get_page(enum palloc_flags flags, void *uaddr) { /* Ensure we are always getting from the user pool */ flags = PAL_USER | flags; /* Attempt to allocate a page, if this comes back null then we need to evict */ void *page = palloc_get_page(flags); /* TODO: not sure if this is right way to check that we ran out of pages Maybe we should check if pages within some count?? */ if(page != NULL) { struct frame *frm = (struct frame*) malloc(sizeof(struct frame)); frm->physical_address = page; frm->user_address = uaddr; frm->owner = thread_current (); list_push_front(&frame_list, &frm->elem); } else { printf("WE RAN OUT OF SPACE. SHIT!\n"); } }
/* Down or "P" operation on a semaphore. Waits for SEMA's value to become positive and then atomically decrements it. This function may sleep, so it must not be called within an interrupt handler. This function may be called with interrupts disabled, but if it sleeps then the next scheduled thread will probably turn interrupts back on. */ void sema_down (struct semaphore *sema) { enum intr_level old_level; ASSERT (sema != NULL); ASSERT (!intr_context ()); old_level = intr_disable (); while (sema->value == 0) { donate_priority(); // list_push_back (&sema->waiters, &thread_current ()->elem); list_insert_ordered (&sema->waiters, &thread_current ()->elem, (list_less_func *) &compare_priority, NULL); thread_block (); } sema->value--; intr_set_level (old_level); }
/* Finds the corresponding entry for fp in the fp_map. Increments num_active, or creates a new entry if none exists. Adds a new fdm_info to the fd_map. Returns the new file descriptor. */ int get_new_fd (struct file *fp) { struct fdm_info * new_fdm = malloc(sizeof(struct fdm_info)); if (new_fdm == NULL) return -1; lock_acquire (&(fm->file_map_lock)); struct fpm_info * result = fpm_from_fp(fp); if(result == NULL) { result = malloc(sizeof(struct fpm_info)); if (result == NULL) { lock_release (&(fm->file_map_lock)); free (new_fdm); return -1; } // No existing file descriptors, initialize new fpm_info result->fp = fp; result->inode = file_get_inode (fp); result->num_active = 0; result->next = fm->fp_map[hash_file(fp)]; init_file_synch (&result->status); fm->fp_map[hash_file(fp)] = result; } result->num_active++; int fd = fm->next_fd; // Create new fdm_info new_fdm->fp = fp; new_fdm->fd = fd; new_fdm->thread_id = thread_current ()->tid; new_fdm->next = fm->fd_map[fd % FD_TABLE_SIZE]; fm->fd_map[fd % FD_TABLE_SIZE] = new_fdm; fm->next_fd++; lock_release (&(fm->file_map_lock)); return fd; }
int sys_open(char* file_name) { if(!*file_name) // empty string check return -1; struct thread *t = thread_current (); int i = 2; for(; i < FDTABLESIZE; ++i) // find the first free FD { if(!t->fd_table[i]) { lock_acquire(&filesys_lock); struct file* fi = filesys_open(file_name); if(fi) t->fd_table[i] = fi; lock_release(&filesys_lock); if(fi) return i; else return -1; } } return -1; }
void close (int fd) { lock_acquire(&file_lock); struct list_elem *e; struct file_descriptor *file_d; struct thread *cur; cur = thread_current (); // would fail if go backward // Why would fail if scan backwards??????? for (e = list_begin (&cur->files); e != list_tail (&cur->files); e = list_next (e)) { file_d = list_entry (e, struct file_descriptor, elem); if (file_d->fd == fd) { file_close (file_d->file); list_remove (&file_d->elem); free (file_d); break; } } lock_release(&file_lock); }
/* Unmaps the mapping for current thread with mapid MAPPING. Each page that has been wriiten to by the process needs to be written back to the file. Each page must be removed from the process' list of virtual pages. */ static void sys_munmap(mapid_t mapping) { struct thread *cur = thread_current(); struct hash *mmap_table = &cur->mmap_table; struct mmap_mapping *mmap = mmap_mapping_lookup(mmap_table, mapping); /* MAPPING must be a mapping ID returned by a previous call to sys_mmap() by the same process that has not yet been unmapped. */ if (mmap == NULL) { sys_exit(ERROR); } /* Removes all pages in mapping from the process' list of virtual pages, and writes pages back to file if they have been written to by the process. */ pages_munmap(mmap); /* Lock must be acquired to call hash_delete() in mmap_mapping_delete(). */ lock_acquire(&cur->mmap_table_lock); /* Remove the mapping MMAP from MMAP_TABLE and free MMAP. */ mmap_mapping_delete(mmap_table, mmap); lock_release(&cur->mmap_table_lock); }
/**Verifies whether every page between buffer start and buffer end are mapped. If not, invokes sys_exit with -1 status code. Else, returns the start address of the buffer. **/ static bool buffer_chk (const char *buffer, unsigned size) { const void *next_address=buffer; /*If size of buffer is less than one full page, then check buffer+remaining size instead of buffer+PGSIZE. */ unsigned i=1; while (i <= size) { if ( (size-i) < PGSIZE ) next_address = next_address + (size-i); else next_address = next_address + PGSIZE; /**If page unmapped, then error. **/ if (pagedir_get_page (thread_current ()->pagedir, next_address) == NULL) { return false; } i+=PGSIZE; } return true; }
/* Up or "V" operation on a semaphore. Increments SEMA's value and wakes up one thread of those waiting for SEMA, if any. This function may be called from an interrupt handler. */ void sema_up (struct semaphore *sema) { enum intr_level old_level; ASSERT (sema != NULL); struct thread *t=NULL; old_level = intr_disable (); if (!list_empty (&sema->waiters)) { struct list_elem *e=list_max(&sema->waiters, thread_max_priority,NULL); t= list_entry(e, struct thread, elem); list_remove(e); // msg(t->name); thread_unblock(t); //thread_unblock (list_entry (list_pop_front (&sema->waiters),struct thread, elem)); } sema->value++; intr_set_level (old_level); if(t && t->priority>thread_current()->priority){ if(intr_context()) intr_yield_on_return(); else thread_yield(); } }
/* * System Call: void exit (int status) * Terminates the current user program, * returning status to the kernel. If the * process's parent waits for it (see below), * this is the status that will be returned. Conventionally, * a status of 0 indicates success and nonzero values indicate errors. */ void exit_handler(int status) { //printf("exiting...\n"); struct thread *t = thread_current(); struct child_record *chr = t->my_record; if(chr!=NULL){ ASSERT(t->tid>1); lock_acquire(&chr->term_m); chr->alive = false; chr->exit_code=status; cond_signal(&chr->terminated,&chr->term_m); //printf("%s sent out termination signal to parent\n",t->name); lock_release(&chr->term_m); } //printf("%s removing all file descriptors\n",t->name); lock_acquire(&fic_m); removeAllFic(); lock_release(&fic_m); //printf("%s removing all children records\n",t->name); child_remove_all(); //printf("thread %s exit...\n",t->name); printf ("%s: exit(%d)\n", t->name, status); thread_exit(); }
/* Sleeps for approximately TICKS timer ticks. Interrupts must be turned on. */ void timer_sleep (int64_t ticks) { ASSERT (intr_get_level () == INTR_ON); /* In order to pass alarm-negative and alarm-zero tests */ if (ticks < 0) return; enum intr_level old_level = intr_disable (); struct thread *current_thread = thread_current (); int64_t start = timer_ticks (); current_thread->wait_till_ticks = start + ticks; /* Add list element of current thread to waiting list */ list_insert_ordered (&waiting_in_line, ¤t_thread->elem, (list_less_func*)&compare_ticks, NULL); /* Wait for timer_interrupt to handle me */ thread_block (); intr_set_level (old_level); }
struct page *zero_new(void *addr, bool write) { struct page *p; p = (struct page *) malloc(sizeof(struct page)); if(p == NULL) { return NULL; } p->type = Z; p->dir = thread_current()->pagedir; p->f_addr = addr; p->load = false; p->write = write; lock_acquire(&lock_list); list_push_back(&pages, &p->elem); lock_release(&lock_list); return p; }
/* Evicts the page held in F. */ void evict(struct frame *f) { uint32_t *pd = thread_current()->pagedir; ASSERT(lock_held_by_current_thread(&f->evicting)); // lock_acquire(&f->page->moving); /* You should never block here. */ ASSERT(f->page != NULL); ASSERT(lock_held_by_current_thread(&f->page->moving)); /* Clear page to prevent further writes. */ pagedir_clear_page(f->page->thread->pagedir, f->page->vaddr); /* If the page had been written to, the changes must be saved. */ if(pagedir_is_dirty(f->page->thread->pagedir, f->page->vaddr)) { if(f->page->status == PAGE_MAPPED) { /* If the page is mapped, write changes back to file. */ bool have_lock = lock_held_by_current_thread(&fs_lock); if(!have_lock) lock_acquire(&fs_lock); if(file_write_at(f->page->file, f->addr, f->page->read_bytes, f->page->ofs) != f->page->read_bytes) PANIC("Didn't write expected %d bytes.", f->page->read_bytes); if(!have_lock) lock_release(&fs_lock); } else { /* Write page to swap. */ ASSERT(pagedir_is_writeable(f->page->thread->pagedir, f->page->vaddr)); ASSERT(f->page->writeable); swap_out(f); } } /* Unset link the page and frame. */ f->page->current_frame = NULL; lock_release(&f->page->moving); f->page = NULL; }
/* Releases LOCK, which must be owned by the current thread. An interrupt handler cannot acquire a lock, so it does not make sense to try to release a lock within an interrupt handler. */ void lock_release (struct lock *lock) { ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); //enum intr_level old_level; //old_level = intr_disable(); //PRE LOCK HOLDER MUST BE THE LOWER ONE , AND HIGHER ONE IS STILL WAITING FOR THE LOWER ONE //THE HIGHER ONE 'S CURRENT PRIORITY IS LOWER ONE'S if (thread_mlfqs) { //roozbeh //no need for checking priority donations lock->holder = NULL; sema_up (&lock->semaphore); } else { struct thread *cur = thread_current(); //NEW //duc: remove lock from list and remove lock holder from lock lock->holder = NULL; list_remove(&lock->elem); /*if any priority change to the donee happends inside the donation,it will save it and restore it after donation finished */ /*been_donated_aux==is_any_priority_change_when_this_thread_is_in_the_case_of_donation*/ if (cur-> been_donated_aux) { thread_set_priority(cur->saved_priority); cur->been_donated_aux = false; } sema_up(&lock->semaphore); take_back_donation(cur); } }
/* Releases LOCK, which must be owned by the current thread. An interrupt handler cannot acquire a lock, so it does not make sense to try to release a lock within an interrupt handler. */ void lock_release (struct lock *lock) { enum intr_level old_level; struct thread *t = thread_current (); struct list_elem *e; ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); old_level = intr_disable (); /* Return donations to threads that want this lock. */ for (e = list_begin (&t->donors); e != list_end (&t->donors); ) { struct thread *donor = list_entry (e, struct thread, donor_elem); if (donor->want_lock == lock) { donor->donee = NULL; e = list_remove (e); } else e = list_next (e); } /* Release lock. */ lock->holder = NULL; sema_up (&lock->semaphore); /* Recompute our priority based on our remaining donations, then yield to a higher-priority ready thread if one now exists. */ thread_recompute_priority (t); thread_yield_to_higher_priority (); intr_set_level (old_level); }
// TODO - Modify Me, give semaphor, add to priority queue, void timer_sleep (int64_t ticks) { ASSERT (intr_get_level () == INTR_ON); intr_disable(); // Disable interrupts in the kernal struct thread *currThread = thread_current(); // Get current thread int64_t start = timer_ticks (); // Get the current number of ticks /* We no longer have a concept of "elapsed time". Instead we want to set this threads wakeup time with an absolute reference to the number of ticks since the OS booted. We could have used elapse time but we would need to store the start time in the thread struct which is unecessary. */ currThread->ticks = start + ticks; // Insert thread into ordered queue list_insert_ordered (&wait_list, &currThread->thread_elem, compare_ticks, NULL); sema_down(&currThread->sem); // Sleep le thread intr_enable(); // Enable interrupts in the kernal }
bool filesys_chdir (const char *dir) { struct dir *target_dir; struct inode *inode = NULL; char parsed_name[NAME_MAX + 1]; if (!parse_path (dir, &target_dir, parsed_name)) { return false; } if (!dir_lookup (target_dir, parsed_name, &inode)) { dir_close (target_dir); return false; } dir_close (target_dir); if (!inode->data.is_dir) { return false; } thread_current ()->cur_dir_sector = inode->sector; return true; }
/* Gets a physical frame if available and maps it to a page obtained from the user pool */ void *get_frame(int flags) { //Check bitmap to see if free frame available struct thread *t = thread_current(); size_t idx = bitmap_scan_and_flip (fr_table->bm_frames, 0, 1, false); void * free_frame; //If available, fetch a page from user pool by calling palloc_get_page if(idx != BITMAP_ERROR) { free_frame = palloc_get_page(flags); if(!free_frame) { /* Evict frame - shouldn't happen here since we scan the bitmap first*/ } } else { //if fetch failed, PANIC for now. Implement evict later. PANIC("out of frames!"); } //else, set the appropriate bit in the ft bitmap (already done) //malloc free frame. map page to frame. Insert frame to hash table. struct frame_entry *frame = malloc(sizeof(struct frame_entry)); if(!frame) { PANIC("Malloc failed:Out of memory!"); } frame->frame = free_frame; frame->pagedir = t->pagedir; hash_insert (&fr_table->ft, &frame->hash_elem); //If bitset, frame used. Else, frame available return free_frame; //Return page address }
/* Write buffer to file */ int write(int fd,void* buffer,unsigned size) { struct thread* t = thread_current(); struct file* f = t->file_desc_table[fd]; int ret_size = 0; if( fd == 1 ) /*Standard output*/ { if(!stdio_lock_init) { stdio_lock_init = true; lock_init(&stdio_lock); } lock_acquire(&stdio_lock); putbuf(buffer,size); ret_size = sizeof(buffer); lock_release(&stdio_lock); } else { ret_size = file_write(f,buffer,size); } return (int)ret_size; }
/* Acquires LOCK, sleeping until it becomes available if necessary. The lock must not already be held by the current thread. This function may sleep, so it must not be called within an interrupt handler. This function may be called with interrupts disabled, but interrupts will be turned back on if we need to sleep. */ void lock_acquire (struct lock *lock) { ASSERT (lock != NULL); ASSERT (!intr_context ()); ASSERT (!lock_held_by_current_thread (lock)); enum intr_level old_level= intr_disable(); //if(!lock_try_acquire(lock)){ // if(lock->holder->priority < thread_current()->priority){ // nested_priority=0; // donate_priority(lock->holder,thread_current()->priority); // } // thread_current()->waiting_lock=lock; sema_down (&lock->semaphore); lock->holder = thread_current (); // thread_current()->waiting_lock=NULL; // list_push_back(&thread_current ()->lock_list,&lock->elem); // } intr_set_level(old_level); }
/* Sleeps for approximately TICKS timer ticks. Interrupts must be turned on. */ void timer_sleep (int64_t ticks) { enum intr_level old_level; /* @A1A */ int64_t start = timer_ticks (); ASSERT (intr_get_level () == INTR_ON); /* while (timer_elapsed (start) < ticks) @A1D */ /* thread_yield (); @A1D */ struct thread_duration *p = /* @A1A */ (struct thread_duration*) malloc(sizeof(struct thread_duration)); /* @A1A */ if (p == NULL) PANIC ("couldn't allocate thread_duration"); /* @A1A */ p->t = thread_current(); /* @A1A */ p->due = start + ticks; /* @A2A */ old_level = intr_disable (); /* @A1A */ list_push_back (&sleeping_list, &p->elem); /* @A1A */ thread_block (); /* @A1A */ intr_set_level (old_level); /* @A1A */ }
/* Releases LOCK, which must be owned by the current thread. An interrupt handler cannot acquire a lock, so it does not make sense to try to release a lock within an interrupt handler. */ void lock_release (struct lock *lock) { ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); enum intr_level level = intr_disable(); bool yield_cpu = false; lock->holder = NULL; if(lock->lock_id!=-1){ struct thread *current_thread = thread_current(); if(current_thread->priority > current_thread->original_priority){ yield_cpu = true; current_thread->priority = current_thread->original_priority; } //if no waiters exist on this lock's semaphore remove it from locks_list if(list_size(&lock->semaphore.waiters)<=1){ struct list_elem *index; for(index=list_begin(&locks_list);index!=list_end(&locks_list);index=list_next(index)){ struct lock_element *current_lock = list_entry(index, struct lock_element, elem); if(current_lock->lock_id == lock->lock_id){ list_remove(index); free(current_lock); break; } } } } sema_up (&lock->semaphore); if(yield_cpu) thread_yield(); intr_set_level(level); }
struct frame* frame_table_set (void* upage, void* kpage){ struct frame* frame_new; ASSERT(is_user_vaddr(upage)); ASSERT(is_kernel_vaddr(kpage)); // TODO: now, frame_find also use frame_lock. This is bad for speed // if kpage frame is already exist, go to else statement lock_acquire(&frame_lock); if(!frame_find(kpage)){ frame_new = malloc(sizeof(struct frame)); frame_new->process = thread_current(); frame_new->upage = (void*)((int)upage&PAGE_MASK); frame_new->kpage = (void*)((int)kpage&PAGE_MASK); list_push_back(&frame_table, &(frame_new->table_elem)); //printf("**** [frame_table_set] frame '%x', upage '%x', kpage '%x'\n",frame_new, frame_new->upage, frame_new->kpage); lock_release(&frame_lock); return frame_new; } else{ lock_release(&frame_lock); return NULL; } }
static void verror(char *msg, va_list ap) { int nargs = count_format_args(msg); int i; struct thread *thread = thread_current(); if (error_system_enabled) { *thread->sp++ = error_var->value; *thread->sp++ = make_byte_string(msg); for (i = 0; i < nargs; i++) *thread->sp++ = va_arg(ap, obj_t); invoke(thread, nargs+1); go_on(); } else if (thread) { obj_t cond = make_vector(nargs+1, NULL); SOVEC(cond)->contents[0] = make_byte_string(msg); for (i = 1; i <= nargs; i++) SOVEC(cond)->contents[i] = va_arg(ap, obj_t); thread_debuggered(thread, cond); } else { obj_t cond = make_vector(nargs, NULL); for (i = 0; i < nargs; i++) SOVEC(cond)->contents[i] = va_arg(ap, obj_t); printf("error: "); vformat(msg, SOVEC(cond)->contents, nargs); putchar('\n'); exit(1); } }
int sys_write(int fd, void *buffer, unsigned size) { if(fd == STDIN_FILENO) return 0; else if(fd == STDOUT_FILENO) { putbuf(buffer, size); return size; } else if(fd < FDTABLESIZE && fd > 1) { struct thread* cur = thread_current (); struct file* fi = cur->fd_table[fd]; if(fi) { int ret; lock_acquire(&filesys_lock); ret = file_write(fi, buffer, size); lock_release(&filesys_lock); return ret; } } return 0; }
/* Sleeps for approximately TICKS timer ticks. Interrupts must be turned on. */ void timer_sleep (int64_t ticks) { struct thread *cur_thread; enum intr_level old_level; ASSERT (intr_get_level () == INTR_ON); if (ticks <= 0) return; old_level = intr_disable (); /* Get current thread and set wakeup ticks. */ cur_thread = thread_current (); cur_thread->wakeup_ticks = timer_ticks () + ticks; /* Insert current thread to ordered sleeping list */ list_insert_ordered (&sleeping_list, &cur_thread->elem, compareWaketicks, NULL); thread_block (); intr_set_level (old_level); }