int process_kill(pid_t pid) { process *p; int level; if(pid < 0 || pid > PROCESS_PID_MAX) return -1; level = level_go(LEVEL_NOINTS); spinlock_grab(&process_spinlock); // find the process p = process_pid_table[pid]; if(!p) { spinlock_release(&process_spinlock); level_return(level); return -1; } // kernel threads can't be killed from another proc if(p->is_kthread && process_current[smp_cpu_id()]->pid != pid) { spinlock_release(&process_spinlock); level_return(level); return -1; } // set the kill-flag (the process is freed in the scheduler) p->exit_flag = 1; spinlock_release(&process_spinlock); level_return(level); // if we just killed ourselves, resched to let the scheduler do its work if(pid == process_current[smp_cpu_id()]->pid) while(1) resched(); return 0; }
/* A value over 1000 indicates a permanent effect */ void minute_status_check(void) { int i; if (Player.status[HASTED]>0) { if (Player.status[HASTED] < 1000) { Player.status[HASTED]--; if (Player.status[HASTED]==0) { mprint("The world speeds up."); calc_melee(); } } } if (Player.status[POISONED]>0) { Player.status[POISONED]--; p_damage(3,POISON,"poison"); if (Player.status[POISONED] == 0) { showflags(); mprint("You feel better now."); } } if (Player.immunity[UNSTOPPABLE]>0) { for(i=0;i<NUMIMMUNITIES;i++) Player.immunity[i]--; if (Player.immunity[UNSTOPPABLE]==1) mprint("You feel vincible again."); } if (Player.status[IMMOBILE]>0) { Player.status[IMMOBILE]--; if (Player.status[IMMOBILE] == 0) mprint("You can move again."); } if (Player.status[SLEPT]>0) { Player.status[SLEPT]--; if (Player.status[SLEPT] == 0) { mprint("You woke up."); } } if (Player.status[REGENERATING]>0) { if ((Player.hp < Player.maxhp) && (Player.mana > 0)){ Player.hp++; Player.mana--; dataprint(); } if (Player.status[REGENERATING] < 1000) { Player.status[REGENERATING]--; if (Player.status[REGENERATING] == 0) { mprint("You feel less homeostatic."); } } } if (Player.status[SLOWED]>0) { if (Player.status[SLOWED] < 1000) { Player.status[SLOWED]--; if (Player.status[SLOWED] == 0) { mprint("You feel quicker now."); calc_melee(); } } } if (Player.status[RETURNING]>0) { Player.status[RETURNING]--; if (Player.status[RETURNING] == 10) mprint("Your return spell slowly hums towards activation..."); else if (Player.status[RETURNING] == 8) mprint("There is an electric tension in the air!"); else if (Player.status[RETURNING] == 5) mprint("A vortex of mana begins to form around you!"); else if (Player.status[RETURNING] == 1) mprint("Your surroundings start to warp and fade!"); if (Player.status[RETURNING] == 0) level_return(); } if (Player.status[AFRAID]>0) { if (Player.status[AFRAID] < 1000) { Player.status[AFRAID]--; if (Player.status[AFRAID] == 0) { mprint("You feel bolder now."); } } } }
pid_t process_create(int pc, int sp, int prio, int is_kthread) { int level; int pid; process *p; process_queue *q; // allocate a process structure p = malloc(sizeof(process)); memset(p,0,sizeof(process)); // grab a process slot level = level_go(LEVEL_NOINTS); spinlock_grab(&process_spinlock); for(pid = 0; pid < PROCESS_PID_MAX; pid++) { if(!process_pid_table[pid]) break; } if(pid == PROCESS_PID_MAX) { spinlock_release(&process_spinlock); level_return(level); free(p); return -1; } process_pid_table[pid] = p; p->pid = pid; spinlock_release(&process_spinlock); level_return(level); // initialize the context if(is_kthread) context_create_kernel(&p->ctx,pc); else context_create_user(&p->ctx,pc,sp); // set the priority and kthread status p->prio = prio; p->is_kthread = is_kthread; // set the preferred CPU - starts out as "none" p->cpu = -1; // put in a run queue q = &process_queues[prio]; level = level_go(LEVEL_NOINTS); spinlock_grab(&process_spinlock); queue_insert(q,p); process_queues_runnable_mask |= (1 << prio); // process can now safely receive messages p->msgstate = PROCESS_MSGSTATE_READY; spinlock_release(&process_spinlock); level_return(level); // done return pid; }
context *process_schedule() { process *p; int prio; int level; // don't preempt if we're at or above LEVEL_NOPREEMPT if(cpu_levels[smp_cpu_id()] >= LEVEL_NOPREEMPT) return &process_current[smp_cpu_id()]->ctx; // make sure we're not interrupted level = level_go(LEVEL_NOINTS); spinlock_grab(&process_spinlock); // find a process to run // if nothing to run then just return if(!process_queues_runnable_mask) { // make sure the currently running process still wants to run if(process_current[smp_cpu_id()]->msgstate == PROCESS_MSGSTATE_READY) { spinlock_release(&process_spinlock); level_return(level); return &process_current[smp_cpu_id()]->ctx; } else { // if not, then we truly have nothing to run, and we can't go back // to the old process - in this case, when all else fails, panic // :-) panic("NO RUNNABLE PROCESSES AND CURRENT PROCESS IS NOT RUNNABLE"); } } // put the currently-running process back on the run queue if it hasn't // been put somewhere else already // we need to do this here so that it has a chance of being chosen below // (if it's the highest-priority process) if(process_current[smp_cpu_id()] && !process_current[smp_cpu_id()]->queue && process_current[smp_cpu_id()]->msgstate == PROCESS_MSGSTATE_READY) { process *oldproc = process_current[smp_cpu_id()]; oldproc->running = 0; oldproc->level = level; queue_remove(oldproc); queue_insert(&process_queues[oldproc->prio],oldproc); process_queues_runnable_mask |= (1 << oldproc->prio); } restart_sched: // highest priority with a runnable process prio = bits_highest_set(process_queues_runnable_mask); if(!process_queues_runnable_mask) panic("NO RUNNABLE PROCESSES"); // take the process off the run queue p = process_queues[prio].head; queue_remove(p); // if the queue is now empty, take note of that if(!process_queues[prio].head) process_queues_runnable_mask &= ~(1 << prio); // if the process has the delete flag set, delete it if(p->exit_flag && (p->level == LEVEL_USER)) { spinlock_release(&process_spinlock); level_return(level); process_do_delete(p); level = level_go(LEVEL_NOINTS); spinlock_grab(&process_spinlock); goto restart_sched; } // set the process state as "running" p->running = 1; p->cpu = smp_cpu_id(); process_current[smp_cpu_id()] = p; // release locks spinlock_release(&process_spinlock); level_return(level); // return new context return &p->ctx; }