/************************************************************************* This file is part of aOS. aOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. aOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with aOS; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Copyright 2001, 2002 Anssi Ylätalo ======================== March005 Bruce Land --add sem_accept function **************************************************************************/ //#include "aos.h" aos_scb *aos_sem_create( UWORD init_val ) { aos_scb *scb_new; AOS_ENTER_CRITICAL; scb_new = (aos_scb *)aos_ctbl.scb_free_list; /* Get next free SCB */ if( scb_new ) { /* SCBs left? */ aos_ctbl.scb_free_list = (aos_scb *)scb_new->next_scb; /* Release SCB from freelist */ scb_new->next_scb = (aos_scb *)aos_ctbl.scb_used_list; /* Link new SCB into SCB used list */ aos_ctbl.scb_used_list = (aos_scb *)scb_new; scb_new->count = init_val; /* Set semaphore's initial value */ scb_new->scb_sem_q = (aos_tcb *)0; /* No task pending on semaphore */ } AOS_EXIT_CRITICAL; //printf("%x ", scb_new); return( scb_new ); } /* About wait(), signal() and HW locking: Since we are in uniprocessor environment, indivisibility is achieved by simply disabling interrupts. After that there is no way for task to loose the processor. Otherwise somekind of hardware locking would be needed. In multi-processor environments possibilities are 'test-and-set'-instruction or instruction to interchange two memory locations. */ //================================================================ void aos_wait( aos_scb *sem ) { aos_tcb *ptcb; AOS_ENTER_CRITICAL; if( sem->count ) { /* Semaphore value >0 ? */ sem->count--; /* Yes, decrement the value */ } else { /* No, we have to wait */ ptcb = (aos_tcb *)sem->scb_sem_q; if( ptcb ) { /* Any tasks in queue? */ while( ptcb->tcb_sem_q ) { /* Yes, find queue's end because */ ptcb = (aos_tcb *)ptcb->tcb_sem_q; /* this is a FIFO, not a stack. */ } ptcb->tcb_sem_q = (aos_tcb *)aos_ctbl.tcb_current; /* Link current process to wait queue */ } else { sem->scb_sem_q = (aos_tcb *)aos_ctbl.tcb_current; /* No, this is the first one */ } aos_ctbl.tcb_current->tcb_sem_q = (aos_tcb *)0; /* Terminate queue properly */ aos_ctbl.tcb_current->status = AOS_TASK_WAITING; /* Now we're waiting */ //printf("%d \n\r",aos_ctbl.tcb_current->status); _aos_schedule(); /* Re-schedule run-queue */ } AOS_EXIT_CRITICAL; } //============================================================ //UBYTE aos_signal( aos_scb *sem ) void aos_signal( aos_scb *sem ) { aos_tcb *ptcb; AOS_ENTER_CRITICAL; ptcb = (aos_tcb *)sem->scb_sem_q; if( ptcb ) { /* Is there pending wait()s? */ //if( ptcb && ptcb->status==AOS_TASK_WAITING ) { //don't dequeue suspended tasks sem->scb_sem_q = (aos_tcb *)ptcb->tcb_sem_q; /* Yes, dequeue the first one */ ptcb->status = AOS_TASK_RUNNABLE; /* Make task runnable */ //sem->count++; //??? --correct-- _aos_schedule(); /* Re-schedule run-queue */ } else { /* No, just increment the semaphore */ sem->count++; } AOS_EXIT_CRITICAL; } //=============================================================== //semaphore accept UWORD aos_sem_accept( aos_scb *sem ) { UWORD temp; AOS_ENTER_CRITICAL; temp = sem->count; if (temp>0) sem->count--; AOS_EXIT_CRITICAL; return temp; }