void syscall_env( struct syscall_packet *scp ) { struct process *proc = NULL; scp->rc = SMK_UNKNOWN_SYSCALL; switch (scp->opcode) { case OP( ENV, ONE ): proc = checkout_process( getpid(), WRITER ); assert( proc != NULL ); scp->rc = set_environment( current_process(), scp->name, scp->ptr, scp->size ); commit_process( proc ); break; case OP( ENV, TWO ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment( current_process(), scp->name, scp->ptr, &(scp->size) ); commit_process( proc ); break; case OP( ENV, THREE ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment_size( current_process(), scp->name, &(scp->size) ); commit_process( proc ); break; case OP( ENV, FOUR ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment_information( current_process(), scp->id, scp->name, &(scp->size) ); commit_process( proc ); break; case OP( ENV, FIVE ): proc = checkout_process( getpid(), WRITER ); assert( proc != NULL ); scp->rc = remove_environment( current_process(), scp->name ); commit_process( proc ); break; } }
int clean_general( struct process *owner, struct wait_info *wait, int rc ) { struct process *proc; struct thread *tr; int count = 0; int clean = 0; struct wait_info *tmp = wait; struct wait_info *old = NULL; while ( tmp != NULL ) { tmp->success = 0; tmp->rc = rc; clean = 0; // Make sure that it's not already locked. if ( owner->pid == tmp->pid ) proc = owner; else proc = checkout_process( tmp->pid, WRITER ); if ( proc != NULL ) { tr = find_thread_with_id( proc, tmp->tid ); if ( tr != NULL ) { set_thread_state( tr, THREAD_RUNNING ); } else clean = 1; // Nothing waiting on this wait. Need to clean it. if ( proc != owner ) commit_process( proc ); } else clean = 1; // Nothing waiting on this wait. Need to clean it. old = tmp; tmp = tmp->next; // Clean the wait if the waiter was not found. if ( clean == 1 ) free( old ); } return count; }
int destroy_global_semaphore( int pid, int sem_id ) { struct sem_link *sl = NULL; struct sem_link *tmp = NULL; struct process *proc = NULL; struct thread *tr = NULL; if ( sem_id < 0 ) return -1; if ( sem_id >= GLOBAL_SEM_COUNT ) return -1; acquire_spinlock( & global_sems_lock ); if ( ( global_sems[ sem_id ].sem_id != sem_id ) || ( global_sems[ sem_id ].pid != pid ) ) { // Invalid or not allowed. release_spinlock( & global_sems_lock ); return -1; } // Tell the waiting guys to go away. sl = global_sems[ sem_id ].waiting_list; while ( sl != NULL ) { tmp = sl; proc = checkout_process( sl->pid, WRITER ); if ( proc != NULL ) { tr = find_thread_with_id( proc, sl->tid ); if ( tr != NULL ) set_thread_state( tr, THREAD_RUNNING ); commit_process( proc ); } sl = sl->next; free( tmp ); } global_sems[ sem_id ].waiting_list = NULL; global_sems[ sem_id ].sem_id = -1; // DELETED! release_spinlock( & global_sems_lock ); return 0; }
int signal_global_semaphore( struct thread* tr, int sem_id ) { struct sem_link *sl; struct process *proc; struct thread *target; acquire_spinlock( & global_sems_lock ); if ( global_sems[ sem_id ].sem_id != sem_id ) { release_spinlock( & global_sems_lock ); return -1; } global_sems[ sem_id ].count -= 1; // wake up any waiting threads sl = global_sems[ sem_id ].waiting_list; if ( sl != NULL ) { proc = checkout_process( sl->pid, WRITER ); if ( proc != NULL ) { target = find_thread_with_id( proc, sl->tid ); if ( target != NULL ) set_thread_state( target, THREAD_RUNNING ); commit_process( proc ); } global_sems[ sem_id ].waiting_list = sl->next; free( sl ); } release_spinlock( & ( global_sems_lock ) ); return 0; }
int begin_wait_thread( int pid, int tid, int *rc ) { int success = -1; int size; struct wait_info *nw = NULL; struct process *proc; struct thread *tr; ASSERT( pid == current_pid() ); proc = checkout_process( pid, WRITER ); ASSERT( proc != NULL ); tr = find_thread_with_id( proc, tid ); if ( tr == NULL ) { commit_process( proc ); return -1; } // -------------------------------- size = sizeof(struct wait_info); nw = (struct wait_info*)malloc( size ); nw->next = NULL; nw->prev = NULL; nw->pid = current_pid(); nw->tid = current_tid(); nw->success = -1; // Assume failure from the very beginning. nw->rc = -1; current_thread()->active_wait = nw; // Set our active wait information. // Now we insert it into the wait list. if ( tr->waits != NULL ) tr->waits->prev = nw; nw->next = tr->waits; tr->waits = nw; // ----------------------------- commit_process( proc ); // ------ Now we go to sleep ------------- proc = checkout_process( current_pid(), WRITER ); if ( proc == NULL ) { /// \todo freak out and handle stuff properly return -1; } disable_interrupts(); atomic_dec( &(proc->kernel_threads) ); set_thread_state( current_thread(), THREAD_WAITING ); commit_process( proc ); enable_interrupts(); sched_yield(); // Release! // Secure ourselves. atomic_inc( &(proc->kernel_threads) ); // Get our process back. proc = checkout_process( current_pid(), WRITER ); if ( proc == NULL ) return -1; current_thread()->active_wait = NULL; commit_process( proc ); // We're back. Return the correct info. *rc = nw->rc; success = nw->success; // nw should have been unlinked by the scheduler. // waiter should have active_wait cleared by the // scheduler as well. // we just need to delete it. free( nw ); return success; }
int begin_wait_process( int pid, int *rc ) { int success = -1; struct wait_info *nw = NULL; struct process *proc; proc = checkout_process( pid, WRITER ); if ( proc == NULL ) return -1; nw = (struct wait_info*)malloc( sizeof(struct wait_info) ); nw->next = NULL; nw->prev = NULL; nw->pid = current_pid(); nw->tid = current_tid(); nw->success = -1; // Assume failure from the very beginning. nw->rc = -1; // Now we insert it into the wait list. if ( proc->waits != NULL ) proc->waits->prev = nw; nw->next = proc->waits; proc->waits = nw; // ----------------------------- commit_process( proc ); // ------ Now we go to sleep ------------- proc = checkout_process( current_pid(), WRITER ); ASSERT( proc != NULL ); current_thread()->active_wait = nw; // Save our active wait. disable_interrupts(); atomic_dec( &(proc->kernel_threads) ); set_thread_state( current_thread(), THREAD_WAITING ); commit_process( proc ); enable_interrupts(); sched_yield(); atomic_inc( &(proc->kernel_threads) ); // Secure this thread. // Get our process back. proc = checkout_process( current_pid(), WRITER ); ASSERT( proc != NULL ); current_thread()->active_wait = NULL; commit_process( proc ); // We're back. Return the correct info. *rc = nw->rc; success = nw->success; // nw should have been unlinked by the scheduler. // waiter should have active_wait cleared by the // scheduler as well. // we just need to delete it. free( nw ); /// \todo active_waits for threads. return success; }