176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modify it under the terms of the GNU General Public License as 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * published by the Free Software Foundation; either version 2 of the 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * License, or any later version. 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is distributed in the hope that it will be useful, but 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WITHOUT ANY WARRANTY; without even the implied warranty of 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * General Public License for more details. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should have received a copy of the GNU General Public License 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * along with this program; if not, write to the Free Software 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/list.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/init.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/process.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** @file 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Processes 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We implement a trivial form of cooperative multitasking, in which 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * all processes share a single stack and address space. 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Process run queue */ 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic LIST_HEAD ( run_queue ); 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Add process to process list 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v process Process 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * It is safe to call process_add() multiple times; further calls will 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * have no effect. 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid process_add ( struct process *process ) { 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( list_empty ( &process->list ) ) { 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( process, "PROCESS %p starting\n", process ); 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ref_get ( process->refcnt ); 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman list_add_tail ( &process->list, &run_queue ); 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( process, "PROCESS %p already started\n", process ); 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Remove process from process list 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v process Process 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * It is safe to call process_del() multiple times; further calls will 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * have no effect. 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid process_del ( struct process *process ) { 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! list_empty ( &process->list ) ) { 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( process, "PROCESS %p stopping\n", process ); 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman list_del ( &process->list ); 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman INIT_LIST_HEAD ( &process->list ); 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ref_put ( process->refcnt ); 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( process, "PROCESS %p already stopped\n", process ); 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Single-step a single process 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This executes a single step of the first process in the run queue, 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and moves the process to the end of the run queue. 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid step ( void ) { 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct process *process; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman list_for_each_entry ( process, &run_queue, list ) { 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman list_del ( &process->list ); 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman list_add_tail ( &process->list, &run_queue ); 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC2 ( process, "PROCESS %p executing\n", process ); 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman process->step ( process ); 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC2 ( process, "PROCESS %p finished executing\n", process ); 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Initialise processes 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void init_processes ( void ) { 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct process *process; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for_each_table_entry ( process, PERMANENT_PROCESSES ) 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman process_add ( process ); 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Process initialiser */ 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct init_fn process_init_fn __init_fn ( INIT_NORMAL ) = { 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .initialise = init_processes, 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 107