Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006 Michael Brown <mbrown (at) fensystems.co.uk>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <gpxe/list.h>
     22 #include <gpxe/init.h>
     23 #include <gpxe/process.h>
     24 
     25 /** @file
     26  *
     27  * Processes
     28  *
     29  * We implement a trivial form of cooperative multitasking, in which
     30  * all processes share a single stack and address space.
     31  */
     32 
     33 /** Process run queue */
     34 static LIST_HEAD ( run_queue );
     35 
     36 /**
     37  * Add process to process list
     38  *
     39  * @v process		Process
     40  *
     41  * It is safe to call process_add() multiple times; further calls will
     42  * have no effect.
     43  */
     44 void process_add ( struct process *process ) {
     45 	if ( list_empty ( &process->list ) ) {
     46 		DBGC ( process, "PROCESS %p starting\n", process );
     47 		ref_get ( process->refcnt );
     48 		list_add_tail ( &process->list, &run_queue );
     49 	} else {
     50 		DBGC ( process, "PROCESS %p already started\n", process );
     51 	}
     52 }
     53 
     54 /**
     55  * Remove process from process list
     56  *
     57  * @v process		Process
     58  *
     59  * It is safe to call process_del() multiple times; further calls will
     60  * have no effect.
     61  */
     62 void process_del ( struct process *process ) {
     63 	if ( ! list_empty ( &process->list ) ) {
     64 		DBGC ( process, "PROCESS %p stopping\n", process );
     65 		list_del ( &process->list );
     66 		INIT_LIST_HEAD ( &process->list );
     67 		ref_put ( process->refcnt );
     68 	} else {
     69 		DBGC ( process, "PROCESS %p already stopped\n", process );
     70 	}
     71 }
     72 
     73 /**
     74  * Single-step a single process
     75  *
     76  * This executes a single step of the first process in the run queue,
     77  * and moves the process to the end of the run queue.
     78  */
     79 void step ( void ) {
     80 	struct process *process;
     81 
     82 	list_for_each_entry ( process, &run_queue, list ) {
     83 		list_del ( &process->list );
     84 		list_add_tail ( &process->list, &run_queue );
     85 		DBGC2 ( process, "PROCESS %p executing\n", process );
     86 		process->step ( process );
     87 		DBGC2 ( process, "PROCESS %p finished executing\n", process );
     88 		break;
     89 	}
     90 }
     91 
     92 /**
     93  * Initialise processes
     94  *
     95  */
     96 static void init_processes ( void ) {
     97 	struct process *process;
     98 
     99 	for_each_table_entry ( process, PERMANENT_PROCESSES )
    100 		process_add ( process );
    101 }
    102 
    103 /** Process initialiser */
    104 struct init_fn process_init_fn __init_fn ( INIT_NORMAL ) = {
    105 	.initialise = init_processes,
    106 };
    107