#include <types.h>
#include <lib.h>
#include <kern/errno.h>
#include <proc.h>
struct proc *allproc[MAX_PROCESSES];
struct lock *lk_allproc;
struct lock *lk_exec;
int next_pid;
static
void
proc_add_to_allproc( struct proc *p, int spot ) {
lock_acquire( lk_allproc );
KASSERT( allproc[spot] == (void *)PROC_RESERVED_SPOT );
allproc[spot] = p;
lock_release( lk_allproc );
}
static
void
proc_found_spot( pid_t *pid, int spot ) {
KASSERT( allproc[spot] == NULL );
allproc[spot] = (void *)PROC_RESERVED_SPOT;
*pid = spot;
next_pid = spot + 1;
lock_release( lk_allproc );
}
static
int
proc_alloc_pid( pid_t *pid ) {
int i = 0;
lock_acquire( lk_allproc );
if( next_pid >= MAX_PROCESSES )
next_pid = 0;
for( i = next_pid; i < MAX_PROCESSES; ++i ) {
if( allproc[i] == NULL ) {
proc_found_spot( pid, i );
return 0;
}
}
for( i = 0; i < next_pid; ++i ) {
if( allproc[i] == NULL ) {
proc_found_spot( pid, i );
return 0;
}
}
lock_release( lk_allproc );
return ENPROC;
}
static
void
proc_dealloc_pid( pid_t pid ) {
lock_acquire( lk_allproc );
KASSERT( allproc[pid] != NULL );
allproc[pid] = NULL;
lock_release( lk_allproc );
}
int
proc_create( struct proc **res ) {
struct proc *p = NULL;
int err = 0;
pid_t pid;
err = proc_alloc_pid( &pid );
if( err )
return err;
p = kmalloc( sizeof( struct proc ) );
if( p == NULL ) {
proc_dealloc_pid( pid );
return ENOMEM;
}
p->p_pid = pid;
err = fd_create( &p->p_fd );
if( err ) {
kfree( p );
proc_dealloc_pid( pid );
return err;
}
p->p_lk = lock_create( "p_lk" );
if( p->p_lk == NULL ) {
fd_destroy( p->p_fd );
kfree( p );
proc_dealloc_pid( pid );
return ENOMEM;
}
p->p_sem = sem_create( "p_sem", 0 );
if( p->p_sem == NULL ) {
lock_destroy( p->p_lk );
fd_destroy( p->p_fd );
kfree( p );
proc_dealloc_pid( pid );
return ENOMEM;
}
p->p_retval = 0;
p->p_is_dead = false;
p->p_nsyscalls = 0;
p->p_nice = 0;
p->p_proc = NULL;
proc_add_to_allproc( p, pid );
*res = p;
return 0;
}
int
proc_clone( struct proc *source, struct proc **target ) {
struct proc *p = NULL;
int err;
err = proc_create( &p );
if( err )
return err;
fd_clone( source->p_fd, p->p_fd );
*target = p;
return 0;
}
void
proc_destroy( struct proc *p ) {
pid_t pid;
pid = p->p_pid;
sem_destroy( p->p_sem );
lock_destroy( p->p_lk );
fd_destroy( p->p_fd );
kfree( p );
proc_dealloc_pid( pid );
}
void
proc_system_init( void ) {
int i = 0;
for( i = 0; i < MAX_PROCESSES; ++i ) {
allproc[i] = NULL;
}
lk_allproc = lock_create( "lk_allproc" );
if( lk_allproc == NULL )
panic( "could not initialize proc system." );
lk_exec = lock_create( "lk_exec" );
if( lk_exec == NULL ) {
lock_destroy( lk_allproc );
panic( "could not create lk_exec." );
}
next_pid = 0;
}
int
proc_get( pid_t pid, struct proc **res ) {
if( pid >= MAX_PROCESSES || pid <= 0 )
return EINVAL;
lock_acquire( lk_allproc );
if( allproc[pid] != NULL && allproc[pid] != (void *)PROC_RESERVED_SPOT ) {
PROC_LOCK( allproc[pid] );
*res = allproc[pid];
lock_release( lk_allproc );
return 0;
}
lock_release( lk_allproc );
return ESRCH;
}
void
proc_test_pid_allocation() {
pid_t pid;
int err;
int i;
for( i = 0; i < 100; ++i ) {
err = proc_alloc_pid( &pid );
if( err )
panic( "failed to allocate a pid. pid allocation is broken.\n" );
kprintf( "awarded PID = %d\n", pid );
proc_dealloc_pid( pid );
}
}